非指针变量和类成员上的新放置
Placement new on non-pointer variables and class members
请考虑以下示例:
#include <iostream>
struct A {
int i;
A(int i)
{
this->i = i;
}
A &operator=(const A &a) = delete;
A(const A &a) = delete;
};
int main()
{
A a(1);
new(&a) A(5);
//a = A(7); // not allowed since = is deleted in A
std::cout << a.i << std::endl;
}
这是一个使用放置 new 运算符的简单示例。由于struct A
的复制构造函数和赋值运算符已被删除(无论出于何种原因(,因此无法更改变量A a
保存的对象,除非将其地址传递给放置新运算符。
其原因可能包括struct A
包含大型数组(例如 100M 个条目(,这些数组必须在赋值运算符和复制构造函数中复制。
问题的第一部分围绕着这种方法的"合法性"。我发现了这个堆栈溢出问题,其公认的答案是
这是完全合法的。 而且没用,因为你不能使用 var [ 在这种情况下
A a
] 来指代你在放置 new 后存储在其中的 [对象] 的状态。任何此类访问都是未定义的行为。 [...]在任何情况下,您都不能在放置新的VAR之后引用它。
为什么会这样呢?我已经看到了放置新运算符的其他几个示例,它们总是类似于
A a(1);
A *b = new(&a) A(2);
// Now use *b instead of a
根据我的理解,使用A a
还是A *b
来访问对象应该无关紧要,因为放置 new 替换了A a
地址处的对象,这当然是A a
。也就是说,我希望总是b == &a
.也许答案不够清楚,这种限制是由于类成员的恒定性。
这是另一个具有相同想法的示例,但是这次struct A
嵌入到另一个对象中:
#include <iostream>
struct A {
int *p;
A(int i)
{
p = new int(i);
}
~A()
{
delete p;
}
A &operator=(const A &a) = delete;
A(const A &a) = delete;
};
struct B {
A a;
B(int i) : a(i)
{
}
void set(int i)
{
a.~A(); // Destroy the old object
new(&a) A(i);
}
};
int main()
{
B b(1);
b.set(2);
std::cout << *(b.a.i) << std::endl;
// This should print 2 and there should be no memory leaks
}
问题基本相同,推理相同。将新放入地址&a
是否有效?
对于此特定代码,您可以a
引用您放在其位置的新对象。 这在 [basic.life]/8 中涵盖
如果在对象的生存期结束后,在重新使用或释放该对象所占用的存储之前,则会在原始对象占用的存储位置创建一个新对象,指向原始对象的指针、引用原始对象的引用或原始对象的名称将自动引用新对象并且,一旦新对象的生存期开始,可用于操作新对象,如果:
新对象的存储完全覆盖原始对象占用的存储位置,并且
- 原始对象的类型不是常量限定的
新对象与原始对象的类型相同(忽略顶级 CV 限定符(,并且
,如果是类类型,则不包含任何类型为常量限定或引用类型的非静态数据成员,并且
原始对象和新对象都不是可能重叠的子对象 ([intro.object](。
强调我的
您检查所有这些要求,以便a
引用您放置在a
内存中的"新"A
。
- 我可以将新的 std::tuple 放入内存映射区域,并在以后读回吗?
- 如何访问子类的新成员函数?
- 在单元测试中,如何在不使用 operator== 的情况下比较两个对象,这可能会错过新成员?
- 非指针变量和类成员上的新放置
- 嵌套的类成员变量不可访问.链表设置.V、下一个和新的问题
- 删除传递给 C++ 中成员函数的新对象
- C :删除对象(使用新的),但成员函数仍然可以正常工作(?)
- 无法将类构造函数中新创建的对象复制到 C++ 中的向量成员
- 将const char * const参数成员分配给新值
- 没有新成员的模板多态性派生类的大小
- 如何使用继承在作为类成员的结构中添加新条目
- 我如何在参考上使用数据成员而不使用新关键字创建对象
- 在类中添加新的成员变量会影响二进制兼容性
- 是标头文件中使用“新”定义的成员指针泄漏
- 与const成员一起安排新的和班级的分配
- BOOST :: ASIO使用成员受体而不是新成员时崩溃
- C++,打开和编辑文本文件中的数字数据,并将结果放入新文件中
- 条件while循环(此社区的新成员)
- 将 int 放入 char 数组是否在法律上需要新的放置
- 具有新数据成员的多态性