使用 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);
}
- 该代码看起来工作正常,所以如果我遗漏了什么,请指导我。这与
class allocator
的工作方式相似吗? (将分配与初始化分开)。
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++ 中为非平凡类型实现它。
我是 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);
}
- 该代码看起来工作正常,所以如果我遗漏了什么,请指导我。这与
class allocator
的工作方式相似吗? (将分配与初始化分开)。
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++ 中为非平凡类型实现它。