我确信这段代码应该是非法的,因为它显然不会起作用,但它似乎被C ++ 0x FCD所允许。
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X(); // according to the standard, the RHS is a placement-new expression
::operator delete(p); // definitely wrong, per litb's answer
delete p; // legal? I hope not
也许你们中的一位语言律师可以解释标准是如何禁止的。
还有一个数组形式:
class X { /* ... */};
void* raw = malloc(sizeof (X));
X* p = new (raw) X[1]; // according to the standard, the RHS is a placement-new expression
::operator delete[](p); // definitely wrong, per litb's answer
delete [] p; // legal? I hope not
This is the closest question我找到了。
编辑:我只是不买标准的限制函数void ::operator delete(void*)
的参数的语言以任何有意义的方式应用于 delete-expression {1}}的操作数的论点。最好的情况是,两者之间的连接非常脆弱,并且许多表达式 允许作为delete
的操作数,这些操作数无效传递给{{ 1}}。例如:
delete
我希望这表明指针是否可以传递给void ::operator delete(void*)
与是否可以将同一指针用作struct A
{
virtual ~A() {}
};
struct B1 : virtual A {};
struct B2 : virtual A {};
struct B3 : virtual A {};
struct D : virtual B1, virtual B2, virtual B3 {};
struct E : virtual B3, virtual D {};
int main( void )
{
B3* p = new E();
void* raw = malloc(sizeof (D));
B3* p2 = new (raw) D();
::operator delete(p); // definitely UB
delete p; // definitely legal
::operator delete(p2); // definitely UB
delete p2; // ???
return 0;
}
的操作数无关。
答案 0 :(得分:7)
标准规则在[basic.stc.dynamic.deallocation] p3
否则,标准库中提供给
operator delete(void*)
的值应该是之前调用标准库中operator new(size_t)
或operator new(size_t, const std::nothrow_t&)
返回的值之一,以及值提供给标准库中的operator delete[](void*)
应该是之前调用标准库中operator new[](size_t)
或operator new[](size_t, const std::nothrow_t&)
返回的值之一。
您的delete
来电将调用图书馆operator delete(void*)
,除非您已覆盖它。既然你没有说过什么,我会假设你没有。
上面的“应该”应该是“行为未定义,如果不是”,所以它不会被误认为是可诊断的规则,而不是[lib.res.on.arguments] p1。这已被n3225更正,所以它不能再被误认为了。
答案 1 :(得分:3)
编译器并不关心p
来自展示位置new
,因此它不会阻止您在对象上发出delete
。通过这种方式,您的示例可以被视为“合法”。
但这不起作用,因为无法显式调用“placement delete
”运算符。只有在构造函数抛出时才会隐式调用它们,因此析构函数可以运行。
答案 2 :(得分:2)
如果
,我想你可能会侥幸逃脱它(在特定的编译器上)new
/ delete
是根据malloc
/ free
和new
实际上使用相同的机制来跟踪与分配相关联的析构函数作为标准new
,以便对delete
的调用可以找到正确的析构函数。 但是它无法移动或安全。
答案 3 :(得分:2)
我在标准的图书馆部分找到了这个,这与尽可能反直觉的位置(IMO)有关:
C ++ 0x FCD(和n3225草案)第18.6.1.3节,[new.delete.placement]
:
这些函数是保留的,是C ++ 程序可能没有定义那些功能 取代标准中的版本 C ++库(17.6.3)。规定 (3.7.4)不适用于这些 预留的经营者安置形式 new和operator delete。
void* operator new(std::size_t size, void* ptr) throw();
void* operator new[](std::size_t size, void* ptr) throw();
void operator delete(void* ptr, void*) throw();
void operator delete[](void* ptr, void*) throw();
但是,定义传递给delete
的合法表达式的部分是5.3.5,而不是3.7.4。