在同一地址多次放置新的是否定义明确/合法
Is it well-defined/legal to placement-new multiple times at the same address?
(注意:这个问题的动机是试图想出预处理器技巧来生成一个无操作分配来回答另一个问题:
接受新对象的宏
所以请记住!(
这是一个人为设计的类:
class foo {
private:
int bar;
public:
foo(int bar) : bar (bar)
{ std::cout << "construct foo #" << bar << std::endl; }
~foo()
{ std::cout << "destruct foo #" << bar << std::endl; }
};
我会这样分配:
// Note: for alignment, don't use char* buffer with new char[sizeof(foo)] !
void* buffer = operator new(sizeof(foo));
foo* p1 = new (buffer) foo(1);
foo* p2 = new (buffer) foo(2);
/* p1->~foo(); */ /* not necessary per spec and problematic in gen. case */
p2->~foo();
在我周围的gcc上,我得到了"预期"的结果:
construct foo #1
construct foo #2
destruct foo #2
这很好,但编译器/运行时是否会将其视为滥用而拒绝,并且仍然站在规范的正确一边?
穿线怎么样?如果我们实际上不关心这个类的内容(假设它只是一个伪对象(,它至少不会崩溃吗,比如在更简单的应用程序中,它用POD int来驱动这个?
在同一内存块上多次执行放置新是非常好的。此外,无论听起来多么奇怪,您甚至不需要销毁已经驻留在该内存中的对象(如果有的话(。该标准明确允许在3.8/4 中
4程序可以通过重复使用存储来结束任何对象的生命周期对象占用的或通过显式调用其析构函数具有非平凡析构函数的类类型的对象。对于对象对于具有非平凡析构函数的类类型,程序不是需要在存储之前显式调用析构函数占用的对象被重复使用或释放;[…]
换句话说,您有责任考虑不为某个对象调用析构函数的后果。
但是,不允许像在代码中那样对同一对象调用析构函数两次。一旦在同一内存区域中创建了第二个对象,就有效地结束了第一个对象的生存期(尽管从未调用过它的析构函数(。现在你只需要破坏第二个对象。
foo* p1 = new (buffer) foo(1);
foo* p2 = new (buffer) foo(2);
p1->~foo();
p2->~foo();
您正在破坏同一个对象两次,仅此一次就是未定义的行为。当你这样做的时候,你的实现可能会决定点披萨,而且它仍然在规范的右侧。
还有一个事实是,您的缓冲区可能没有正确对齐以放置foo类型的对象,这也是非标准C++(根据C++03,我认为C++11放宽了这一点(。
更新:关于标题中指定的问题,
在同一地址多次放置新的是否定义明确/合法?
是的,如果它指向原始内存,那么在同一地址多次放置新内存是否定义良好。
否-这看起来不对。
当您使用放置new
时,对象将在您传递的地址处构造。在本例中,您将两次传递同一地址(即&buffer[0](,因此第二个对象只是擦除已在该位置构造的第一个对象。
编辑:我想我不明白你想做什么。
如果您有一个通用的对象类型(可能有可能分配/释放资源的非平凡的ctor/dtor(,并且您通过将new
放在第一个对象的顶部而不首先显式调用它的析构函数来擦除第一个对象,那么这至少是内存泄漏。
- 此递归模板类型定义是否有效C++?
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 越界成员函数定义是否需要一个完全限定的类名,直到全局范围
- C++标准是否定义了结构中成员函数的函数内定义是否必须具有静态链接?
- 带有"struct structname<..>"的模板定义是否正确?
- NTRUEncrypt:使用开源标准算法中的描述无法正确找到两个多项式的GCD,无法定义是否存在多边形的逆
- 定义重载C++函数模板的原型时,使用其名称引用以前的定义是否合法?
- 命名空间的定义是否可以跨越多个翻译单元
- 头文件中的类声明和定义是否在每个包含上编译
- 这个无括号的C预处理器定义是否安全
- char的实现定义是否会影响std::string
- 对内联函数有不同的定义是否是一种未定义的行为
- 同一字符串的多个#定义是否使用相同的常量字符串
- 根据编译时常量,使用相同的标识符 #define 或类型定义是否被认为是可接受的做法?
- 显式模板实例化定义是否也抑制隐式实例化
- 构造函数定义是否可以以 "class" 关键字为前缀?
- 类中的函数定义是否占用类大小的一部分?
- 名称空间作用域构造函数定义是否需要类限定的标识符
- i=i++;未定义.是否i=foo(i++)也未定义
- "volatile"的定义是否如此不稳定,还是 GCC 存在一些标准合规性问题?