首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在新位置获得的指针上使用操作符delete的合法性

在新位置获得的指针上使用操作符delete的合法性
EN

Stack Overflow用户
提问于 2010-12-11 18:24:09
回答 4查看 1.3K关注 0票数 12

我确信这段代码应该是非法的,因为它显然是行不通的,但是它似乎是被C++0x FCD允许的。

代码语言:javascript
复制
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

也许你们中的一个语言律师可以解释一下标准是怎么禁止的。

还有一个数组表单:

代码语言:javascript
复制
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操作数的论点。充其量,这两者之间的连接是极其脆弱的,许多表达式被允许作为操作数传递到delete,而这些操作数不能传递给void ::operator delete(void*)。例如:

代码语言:javascript
复制
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;
}

我希望这表明,是否可以将指针传递给void operator delete(void*),这与该指针是否可以用作delete的操作数无关。

EN

回答 4

Stack Overflow用户

发布于 2010-12-11 18:59:30

basic.stc.dynamic.deallocationp3的标准规则

否则,标准库中提供给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.argumentsp1并没有这样做。这是由n3225纠正的,所以不会再弄错了。

票数 7
EN

Stack Overflow用户

发布于 2010-12-11 18:39:55

编译器并不真正关心p来自位置new调用,因此它不会阻止您在对象上发出delete。这样,你的例子可以被认为是“合法的”。

但是,这是行不通的,因为“放置delete”运算符不能显式调用。只有在构造函数抛出时才隐式调用它们,因此析构函数才能运行。

票数 3
EN

Stack Overflow用户

发布于 2010-12-11 18:46:48

我想您可能会(在特定的编译器上),如果

  1. new/delete是根据malloc/free
  2. 实现的。standard new实际上使用了与标准new相同的机制来跟踪与分配相关的析构函数,这样对delete的调用可以找到正确的析构函数。

但它不可能是便携的或安全的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4418220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档