使用 operator new 和 placement new 创建非默认可构造对象的动态数组

Using operator new and placement new to create a dynamic array of non-default constructible objects

我是 placement new 的新手,所以我想将分配与初始化分开使用它 operator new 来分配和构造我的用户定义类型的数组 class 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);

}

please guide me if I've missed something.

Foo 似乎还不错。但更一般地说,该方法不是异常安全的。如果 class 构造函数之一抛出异常,那么你的分配就会泄漏,之前构造的对象将不会被销毁。

And is this similar to how class allocator works?

很像。一些差异:

  • std::allocator<T>::allocate 使用 ::operator new(std::size_t, std::align_val_t) 并且 std::allocator<T>::deallocate 自 C+++17 起调用 ::operator delete(void*, std::align_val_t)。这是支持过度对齐类型所必需的。
  • 从技术上讲,您永远不会开始数组的生命周期。这在实践中不是一个大问题。没有任何实用的方法可以在重用内存中创建动态数组。虽然,自 C++20 std::allocator<T>::allocate 实际上确实开始了 T 数组的生命周期(没有开始对象的生命周期)。技术上没有办法在标准 C++ 中为非平凡类型实现它。