主要有两种情况:
第一种情况是——例如在嵌入式系统中——你必须在给定的众所周知的地方构造一个对象。
第二个是当您出于某种原因想要以默认方式以外的方式管理内存时。
在 C++ 中,像 pA = new(...) A(...) 这样的表达式会连续做两件事:
- 调用
void* operator new(size_t, ...) 函数,随后调用
- 致电
A::A(...)。
由于调用 new 是调用 A::A() 的唯一方法,因此向 new 添加参数允许专门化不同的方式来管理内存。最琐碎的就是“使用已经通过其他方式获得的内存”。
当需要将分配和构造分开时,这种方法很好。典型的例子是std::allocator,其目的是为给定的数量分配未初始化的内存,而对象的构造发生在后面。
例如,在std::vector 中会发生这种情况,因为它必须分配一个通常比其实际size 更宽的capacity,然后在已经存在push_back 的空间中构造对象存在。
事实上,默认的 std::allocator 实现,当要求分配 n 个对象时,会执行 return reinterpret_cast<T*>(new char[n*sizeof(T)]),因此分配空间,但实际上不构造任何东西。
承认 std::vector 存储:
T* pT; //the actual buffer
size_t sz; //the actual size
size_t cap; //the actual capacity
allocator<T> alloc;
push_back 的实现可以是:
void vector<T>::push_back(const T& t)
{
if(sz==cap)
{
size_t ncap = cap + 1+ cap/2; //just something more than cap
T* npT = alloc.allocate(ncap);
for(size_t i=0; i<sz; ++i)
{
new(npT+i)T(pt[i]); //copy old values (may be move in C++11)
pt[i].~T(); // destroy old value, without deallocating
}
alloc.deallocate(pt,cap);
pT = npT;
cap = ncap;
// now we heve extra capacity
}
new(pT+sz)T(t); //copy the new value
++sz; //actual size grown
}
本质上,需要将分配(与整个缓冲区相关)与元素的构造(必须发生在已经存在的缓冲区中)分开。