作为优化策略的一部分,我想“假装”我实际上是在堆上分配一个对象,而事实上,我只是重用一个预先存在的对象,而应用程序的其余部分却没有注意到,因为对返回的地址执行检查,并且将永远不必访问对象中的任何字段。除此之外,类构造函数没有副作用。
因此,我想知道以下程序是否表现出用标准的话来定义良好,特定于实现,未定义或完全无效的行为。
#include <memory>
#include <cassert>
class Base {
public:
Base(){}
virtual ~Base(){}
};
class Derived: public Base {
public:
using Base::Base;
static void *operator new(std::size_t s) {
static void *mem = ::operator new(s);
return mem;
}
static void operator delete(void *mem) {
/* no-op */
}
};
int main() {
using Ptr = std::unique_ptr<Base>;
Ptr p1 { new Derived };
Ptr p2 { new Derived };
Ptr p3 { new Derived };
Ptr p4 { new Derived };
// assert just in this test, not in the real program
assert(p1 == p2 && p2 == p3 && p3 == p4);
return 0;
}
阅读当前的C ++工作草案(N4835第6.7.2.9节,似乎无效:
如果两个生命周期重叠且不是位域的对象可能具有相同的地址,一个嵌套在另一个中,或者如果至少一个是零大小的子对象并且它们是不同类型; 否则,它们具有不同的地址并占用不相交的存储字节²⁹。
但是,上段所指的注释29指出:
根据“假设”规则允许实现在同一机器地址上存储两个对象或根本不存储对象如果程序无法观察到差异。
如开头所述,在我的情况下,程序不会在乎此对象的分配地址,所需要做的就是可以用operator new
分配它,而用operator delete
摆脱它。 ,因此似乎符合注释29的要求。这正确吗?
[basic.stc.dynamic.allocation] / 2