C++ 当我们重载新操作符时,是否有必要重载新操作符?
我有下面一段代码C++ 当我们重载新操作符时,是否有必要重载新操作符?,c++,C++,我有下面一段代码 class Test { public: Test(){} Test(int i) {} void* operator new (size_t size) { void *p = malloc(size); return p; } //void* operator new (size_t size, Test *p) //{ // return p; //} }; int main() {
class Test
{
public:
Test(){}
Test(int i) {}
void* operator new (size_t size)
{
void *p = malloc(size);
return p;
}
//void* operator new (size_t size, Test *p)
//{
// return p;
//}
};
int main() {
Test *p = new Test;
int i = 10;
new(p) Test(i);
}
除非我取消注释重载的placement new operator函数,否则上述代码不会在VisualStudio中编译。
如果我注释掉正常重载的new,在这种情况下,它也可以正常工作。
重载普通新运算符时是否必须重载placement new(如果该类需要使用placement new)
此处未显示位置删除相关代码。通常不显示,因为它不经常使用。但这可能是必要的,因为在类中重载
操作符new
时,它会隐藏全局::操作符new
的所有重载
因此,如果您想在该类的对象上使用placement new,请执行以下操作:;否则不要。这同样适用于nothrow
new
<> P>如果你刚刚改变了分配方案,你会惊奇地发现某处有人在你背后使用新的布局,这可能是在应用这个创可贴之前要进行的调查。
如果该类在标准库容器中使用,而不是直接与new
一起使用,则自定义分配方案应由分配器类定义,而不是重载。默认分配器std::allocator
不考虑成员运算符new
重载,而是绕过它们。见下文
免责声明:class scope
operator new
重载主要用于调试,即使如此,也很难获得可靠的有意义语义。注意:
- 您还需要重载
操作员删除
。(本问题示例中未进行此操作。)
- 重载将被限定语法
绕过。你无法阻止这种绕过。这就是::new T
分配事物的方式。您可以为您的类型专门化std::allocator
,但这已经是兔子洞的一部分了std::allocator
-
对于每个<代码>:由任何库引入的运算符new < /COD>重载,包括从<代码> <代码>中的规范放置,您必须考虑它是否适用于您的类并决定是否添加重载,否则将与不合格代码<新> <代码>表达式进行争用。
- 对于类中采用的每个
,必须提供具有正确语义的相应成员位置::运算符new
。如果构造函数异常退出,则调用此函数。只有在非常特定的情况下,在可能资源受限的池中,如果没有它,才会导致内存泄漏运算符delete
总之,成员
运算符new
是防御编码的对立面。对于类,默认情况下不存在放置新运算符,因此当您调用new(p)Test(i)代码> C++编译器找不到上面例子中注释函数的定义。如果您取消对类的placement运算符new的注释,并注释掉“normal”运算符,那么将使用默认的“normal”新运算符,并且您的代码将被编译。std::_构造的实现使用全局placement new。因此,对STL兼容性的关注不应该成为关注的焦点。但担心破坏现有的代码,这可能是书面的
新的((void*)p)事物代码>
而不是
::新的((void*)p)事物代码>
这当然是一个正确的观点。实际上,无论何时出于这个原因实施自定义new
时,实施placement和nothrownew
都是一个好主意。如果不能提供new和delete(不要忘记数组形式)的六个版本,您可能会破坏现有代码。代码中不经常使用placementnew
,但STL容器经常使用它来将内存分配与对象构造分开。@Philip:那是个危险信号,由于std::allocator
从::operator new
获取内存。在这种情况下,解决方案是实现一个自定义分配器,而不是启用标准分配器。@Potato:不,这不是问题所在。问题是,如果std::vector
需要放置new
来构建MyClass
,那么MyClass
最好提供一个。vector
从哪里获得内存并不重要。@Philip:如果vector
从错误的地方获得内存,那就是一个bug。实现自定义分配器也可能需要新的位置(无论如何,根据法律的规定),因此它可能会以某种方式返回。也许我不应该急于下结论,但这绝对是个问题。