是否可以将堆栈对象地址赋给placement new
Is it okay to give a stack object address to placement new?
忽略了这种做法的有用性。(当然,现实生活中的例子是受欢迎的。)
例如,以下程序输出a
的正确值:
#include <iostream>
using namespace std;
int main()
{
int a = 11111;
int i = 30;
int* pi = new (&i) int();
cout << a << " " << endl;
}
但是new-allocation是不是应该在i
附近创建一些簿记信息(为了正确的后续释放),在这种情况下应该破坏i
周围的堆栈?
是的,对指向堆栈上对象的指针执行place -new是完全可以的。它只会使用那个特定的指针来构造对象。placementnew实际上并没有分配任何内存——您已经提供了这一部分。它只做构造。随后的删除实际上不会是delete
—没有位置delete
—因为您所需要做的就是调用对象的析构函数。实际的内存是由其他东西管理的——在这个例子中是堆栈对象。
例如,给定这个简单类型:
struct A {
A(int i)
: i(i)
{
std::cout << "make an An";
}
~A() {
std::cout << "delete an An";
}
int i;
};
下面是完全合理的,行为良好的代码:
char buf[] = {'x', 'x', 'x', 'x', 0};
std::cout << buf << std::endl; // xxxx
auto a = new (buf) A{'a'}; // make an A
std::cout << a->i << std::endl; // 97
a->~A(); // delete an A
唯一无效的情况是,如果您的放置-新建对象的存续期超过了您新建的对象的存续期——出于同样的原因,返回悬空指针总是不好的:
A* getAnA(int i) {
char buf[4];
return new (buf) A(5); // oops
}
new位置将构造元素的位置,并且不分配内存。
本例中的"簿记信息"是返回的指针,应该用来销毁放置的对象。
没有与位置相关的删除操作,因为位置是一个构造。因此,放置new所需的"清理"操作是销毁。
"通常步骤"为
- 分配的内存
- 在适当位置构建元素
- 销毁元素(2的反转)
- 'Deallocate'内存(1的反转)
(其中内存可以是堆栈内存,既不需要显式分配也不需要释放,而是随着堆栈数组或对象来来回回)
注意:如果将对象"放置"到堆栈中相同类型的内存中,应该记住在对象的生命周期结束时将自动销毁。
{
X a;
a.~X(); // destroy a
X * b = new (&a) X(); // Place new X
b->~X(); // destroy b
} // double destruction
不可以,因为您不需要delete
一个已经更新了位置的对象,所以您需要手动调用它的析构函数。
struct A {
A() { std::cout << "A()n"; }
~A() { std::cout << "~A()n"; }
};
int main()
{
alignas(A) char storage[sizeof(A)];
A *a = new (storage) A;
std::cout << "hi!n";
a->~A();
std::cout << "bye!n";
}
输出:A()
hi!
~A()
bye!
在你的例子中,也不需要调用析构函数,因为int
是平凡可析构的,这意味着它的析构函数无论如何都是无操作的。
请注意,不要在仍然存活的对象上调用place -new,因为不仅会破坏它的状态,而且它的析构函数也会被调用两次(一次是在手动调用时,还有一次是在原始对象应该被删除时,例如在其作用域结束时)。
新增的是建设,而不是分配,因此无需担心记账信息。
我现在可以想到一个可能的用例,尽管它(以这种形式)将是一个糟糕的封装示例:
#include <iostream>
using namespace std;
struct Thing {
Thing (int value) {
cout << "such an awesome " << value << endl;
}
};
union Union {
Union (){}
Thing thing;
};
int main (int, char **) {
Union u;
bool yes;
cin >> yes;
if (yes) {
new (&(u.thing)) Thing(42);
}
return 0;
}
住在这里即使在某个成员函数中隐藏了位置new,构造仍然在堆栈上进行。
So:我没有看标准,但是不明白为什么不允许在堆栈上放置new。
一个真实世界的例子应该在https://github.com/beark/ftl…在它们的递归联合中,用于sum类型
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 使用泛型成员变量"placement new"结构/类数组的正确方法是什么?
- 基于索引的 alloca 返回的指针访问和"placement new"的效果
- 无法调用使用 malloc/placement new 创建的类上的虚函数
- 通过 placement-new 手动构造一个简单的基类
- 为什么shared_ptr使用placement new
- Constexpr placement new?
- C++ placement new
- placement new和vector::data()可以用来替换向量中的元素吗
- 在不先显式调用析构函数的情况下,在旧对象上使用placement new是否危险
- 我们是否需要为分配"placement new" "simple POD classes"显式调用析构函数?
- 删除使用placement new分配的动态多态对象
- C++ Placement new and Constructor call
- 在全局变量上使用placement new时,有什么不正确的地方吗
- 我们还需要"placement new"和"operator new"吗?
- 为什么我要使用placement new
- "placement new"优势方案
- 从动态创建的数组构造pod对象时,是否推荐使用placement new ?
- C++ Volatile Placement New
- 你能/如何重新分配用placement new创建的c++对象?