Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用运算符new和placement new创建非默认可构造对象的动态数组_C++_New Operator_Placement New - Fatal编程技术网

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
,就像您可以
数据放入其中一样。更简单、更易于维护。@RemyLebeau
elemType*data=…
(打字)如果使用
std::allocator::allocate
是否有方法使用
pf
而不是
data
调用,或者您是否仅限于在
data
上调用
.deallocaate()
,即使用
.allocate()获得的实际指针
?@DavidC.Rankin我不明白你所说的
数据是什么意思
?很抱歉,我在看define
ALLOCA
触发使用
std::allocator
(这可能应该是一个单独的问题——我会删除一些注释,但我很好奇我看的是否正确)@DavidC.Rankin是的,使用分配器与使用
std::aligned_storage
是完全不同的。您将
operator::new
的结果传递给
operator::delete
,并将
std::allocator::allocate
的结果传递给
std::allocator::deallocate
,就像将
new
的结果传递给
delete
delete[]
。谢谢你——这就是我挂断电话的地方。