Mag*_*ero 2 c++ placement-new dynamic-memory-allocation object-construction
我试图理解C++ 中的放置新表达式。
\n这个 Stack Overflow 答案指出,这T* p = new T(arg);相当于
void* place = operator new(sizeof(T)); // storage allocation\nT* p = new(place) T(arg); // object construction\nRun Code Online (Sandbox Code Playgroud)\n这delete p;相当于
p->~T(); // object destruction\noperator delete(p); // storage deallocation\nRun Code Online (Sandbox Code Playgroud)\n为什么我们需要在对象构造中放置 new 表达式T* p = new(place) T(arg);,\xe2\x80\x99t 与以下等价吗?
T* p = (T*) place;\n*p = T(arg);\nRun Code Online (Sandbox Code Playgroud)\n
首先要注意的是,这*p = T(arg);是一个作业,而不是一个构造。
现在让我们阅读标准([basic.life]/1):
...类型对象的生命周期
T从以下时间开始:
T获得具有正确对齐方式和类型大小的存储,并且- 其初始化(如果有)已完成(包括空初始化)
对于一般类型T,如果使用放置,初始化可能已经完成new,但事实并非如此。正在做
void* place = operator new(sizeof(T));
T* p = (T*)place;
Run Code Online (Sandbox Code Playgroud)
不开始 的生命周期*p。
同一部分内容如下([basic.life]/6):
...在对象的生命周期开始之前,但在分配该对象将占用的存储空间之后...任何表示该对象将...所在的存储位置的地址的指针都可以使用,但只能使用以有限的方式。... 如果出现以下情况,则程序具有未定义的行为: ...
- 指针用于访问非静态数据成员或调用对象的非静态成员函数,...
operator=是一个非静态成员函数,执行*p = T(arg);,相当于p->operator=(T(arg)),会导致未定义的行为。
一个简单的示例是包含一个指针作为数据成员的类,该指针在构造函数中初始化并在赋值运算符中取消引用。如果没有放置,new则不会调用构造函数,并且该指针不会被初始化(完整示例)。