我是 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
的工作方式相似吗? (与初始化分开分配)。答案 0 :(得分:2)
如果我错过了什么,请指导我。
对于 Foo
来说似乎不错。但更一般地说,这种方法不是异常安全的。如果其中一个类构造函数抛出异常,那么您的分配就会泄漏,并且之前构造的对象不会被销毁。
这与类分配器的工作方式相似吗?
非常相似。一些差异:
std::allocator<T>::allocate
从 C+++17 开始使用 ::operator new(std::size_t, std::align_val_t)
和 std::allocator<T>::deallocate
调用 ::operator delete(void*, std::align_val_t)
。这是支持过度对齐的类型所必需的。std::allocator<T>::allocate
实际上确实开始了 T
数组的生命周期(不开始对象的生命周期)。对于非平凡类型,技术上无法在标准 C++ 中实现它。