C++ NoFieldsClass::operator new(std::size_t):标准是否允许它每次返回相同的地址';什么事?

C++ NoFieldsClass::operator new(std::size_t):标准是否允许它每次返回相同的地址';什么事?,c++,memory-management,language-lawyer,new-operator,C++,Memory Management,Language Lawyer,New Operator,作为优化策略的一部分,我想“假装”我实际上在堆上分配一个对象,而实际上我只是重用一个预先存在的对象,而应用程序的其余部分根本不会注意到,因为不会对返回的地址执行任何检查,也不必访问对象中的任何字段。除此之外,类构造函数没有任何副作用 因此,我想知道,按照标准的说法,以下程序是否表现出定义良好、特定于实现、未定义或完全无效的行为 #包括 #包括 阶级基础{ 公众: Base(){} 虚拟~Base(){} }; 派生类:公共基{ 公众: 使用Base::Base; 静态void*运算符新(标准::

作为优化策略的一部分,我想“假装”我实际上在堆上分配一个对象,而实际上我只是重用一个预先存在的对象,而应用程序的其余部分根本不会注意到,因为不会对返回的地址执行任何检查,也不必访问对象中的任何字段。除此之外,类构造函数没有任何副作用

因此,我想知道,按照标准的说法,以下程序是否表现出定义良好、特定于实现、未定义或完全无效的行为

#包括
#包括
阶级基础{
公众:
Base(){}
虚拟~Base(){}
};
派生类:公共基{
公众:
使用Base::Base;
静态void*运算符新(标准::大小\u t s){
静态void*mem=::运算符新建;
返回mem;
}
静态void运算符删除(void*mem){
/*无操作*/
}
};
int main(){
使用Ptr=std::unique_Ptr;
Ptr p1{新导出的};
Ptr p2{新派生的};
Ptr p3{新派生的};
Ptr p4{新派生的};
//仅在该测试中断言,而不是在实际程序中断言
断言(p1==p2&&p2==p3&&p3==p4);
返回0;
}

当前C++工作草案中的读数<7.7.2.9,似乎无效:

两个生命周期重叠且不是位字段的对象可能具有相同的地址,如果 一个嵌套在另一个中,或者至少有一个是大小为零的子对象,并且它们的类型不同否则,它们具有不同的地址并占用不相交的存储字节2⁹.

然而,上文提到的注释29指出:

根据“仿佛”规则允许实现在同一机器地址存储两个对象,或者如果程序无法观察到差异,则不存储任何对象

如开头所述,在我的情况下,程序不能不关心分配此对象的地址,所需的只是可以使用
运算符new
分配它,并使用
运算符delete
删除它,因此它似乎符合注29的要求。这是正确的吗

[basic.stc.dynamic.allocation]/2分配函数尝试分配请求的存储量。。。如果请求成功,则返回的值应为 非空指针值(7.11)
p0
与以前返回的任何值不同,除非该值
p1
随后被传递给
运算符delete


强调我的。

p1==p2等意味着您的程序非常关心对象的地址。程序确实观察到了差异。这只是我在示例中使用的一个断言,用于显示我希望结果是什么。真正的程序不执行这样的检查。“IF”规则允许“实现”——编译器、链接器、标准库等——而不是C++程序。如果断点构造函数,它会被调用第二次。如果是这样的话,我认为这是行不通的。感觉非常有问题(ish)。为什么不使用单例呢?构造函数会被调用,但它是一个不做任何事情的构造函数。我或许应该在问题中具体说明这一点。单例在这里是没有用的,因为这只是不使用这种方法的其他情况的一个特殊情况。如示例所示,
运算符new
仅在可能无限多的派生类中的一个类中重载。谢谢,我自己无法发现这一点。然而,我想知道两件事:1)这如何符合上面提到的“似乎”规则?2) 返回同一地址是否真的有可能在其自身特定的领域内产生一个行为不端的程序,并保证上述“仿佛”规则适用?1)我看不出“仿佛”规则是如何相关的。2) 未定义的行为是未定义的。“似乎有效”是未定义行为的一种可能表现形式。就我个人而言,我不会依赖它,但有些人喜欢过危险的生活。