C++ 使用运算符new和placement new创建非默认可构造对象的动态数组
我不熟悉C++ 使用运算符new和placement new创建非默认可构造对象的动态数组,c++,new-operator,placement-new,C++,New Operator,Placement New,我不熟悉placement new,因此我想使用它将分配与初始化分离,并使用操作符new来分配和构造我的用户定义类型类Foo的数组 以下是我尝试过的: struct Foo{ Foo(int x) : x_(x){ std::cout << "Foo(int)\n"; } ~Foo(){ std::cout << "~Foo()\n"; } int x_ = 0
placement new
,因此我想使用它将分配与初始化分离,并使用操作符new
来分配和构造我的用户定义类型类Foo
的数组
以下是我尝试过的:
struct Foo{
Foo(int x) : x_(x){
std::cout << "Foo(int)\n";
}
~Foo(){
std::cout << "~Foo()\n";
}
int x_ = 0;
};
int main(){
Foo* pf = static_cast<Foo*>(operator new[](10 * sizeof(Foo) ) );
for(int i = 0; i != 10; ++i)
new(pf + i)Foo(i * 7);
for(int i = 0; i != 10; ++i)
std::cout << pf[i].x_ << ", ";
std::cout << '\n';
for(int i = 0; i != 10; ++i)
pf[i].~Foo();
operator delete[](pf);
}
structfoo{
Foo(int x):x_x(x){
标准::cout
如果我错过了什么,请引导我
对于Foo
,这种方法似乎很好。但更一般地说,这种方法不是异常安全的。如果某个类构造函数抛出,那么您的分配就会泄漏,以前构造的对象也不会被销毁
这和类分配器的工作原理类似吗
非常相似。有一些区别:
std::allocator::allocate
使用::运算符new(std::size\u t,std::align\u val\u t)
和std::allocator::deallocate
调用::运算符delete(void*,std::align\u val\u t)
自C++17以来。这是支持过度对齐类型所必需的
- 从技术上讲,您永远不会开始数组的生存期。这在实践中不是一个大问题。没有任何实用的方法在可重用内存中创建动态数组。虽然,自从C++20
<代码> STD::分配:实际上启动了一个数组的生存期<>代码> t>代码>(不启动对象的生命周期)。在技术上,在标准C++中,没有实现非平凡类型的方法。
这在我看来很好,但如果Foo是过度对齐的,这就不符合Foo的对齐要求。我会将其更改为Foo*pf=static_cast(操作符new[](10*sizeof(Foo),std::align_val_t{alignof(Foo)});
如果Foo是一个模板类型,我会去掉操作符new[]
和操作符delete[]
总共,用于数组,例如:使用elemType=std::aligned_storage_t;elemType data*=new elemType[10];Foo*pf=reinterpret_cast(data);…for(int i=0;i<10;++i){new(pf+i)Foo(…)}…for(int i=0;i<10;++i)pf[i]。~Foo();…delete[]data;
您可以使用std::vector
,就像您可以将数据放入其中一样。更简单、更易于维护。@RemyLebeauelemType*data=…
(打字)如果使用std::allocator::allocate
是否有方法使用pf
而不是data
调用,或者您是否仅限于在data
上调用.deallocaate()
,即使用.allocate()获得的实际指针
?@DavidC.Rankin我不明白你所说的数据是什么意思
?很抱歉,我在看defineALLOCA
触发使用std::allocator
(这可能应该是一个单独的问题——我会删除一些注释,但我很好奇我看的是否正确)@DavidC.Rankin是的,使用分配器与使用std::aligned_storage
是完全不同的。您将operator::new
的结果传递给operator::delete
,并将std::allocator::allocate
的结果传递给std::allocator::deallocate
,就像将new
的结果传递给delete
或delete[]
。谢谢你——这就是我挂断电话的地方。