在Herb Sutter的Exceptional C ++书中,在第12项-编写异常安全代码-第5部分中,作者使用全局运算符new和delete(单)而不是全局运算符new []和delete []进行分配数组的内存,而无需调用默认构造函数。
我的问题是:如果要创建数组,为什么他不调用运算符的数组版本?析构函数同样适用。请参阅下面的变量test1
和test2
。
如果全局运算符new和new []使用相同的参数执行相同的操作,那么我不明白为什么两者都存在,如果不是出于语义正确性的考虑。
以下代码摘自本书:
...
template <class T>
StackImpl<T>::StackImpl( size_t size )
: v_( static_cast<T*>
( size == 0
? 0
: operator new(sizeof(T)*size) ) ),
vsize_(size),
vused_(0)
{
}
template <class T>
StackImpl<T>::~StackImpl()
{
destroy( v_, v_+vused_ ); // this can't throw
operator delete( v_ );
}
...
// construct() constructs a new object in
// a given location using an initial value
//
template <class T1, class T2>
void construct( T1* p, const T2& value )
{
new (p) T1(value);
}
// destroy() destroys an object or a range
// of objects
//
template <class T>
void destroy( T* p )
{
p->~T();
}
template <class FwdIter>
void destroy( FwdIter first, FwdIter last )
{
while( first != last )
{
destroy( &*first );
++first;
}
}
起初我并不完全了解它,所以我做了一点测试:
struct OperatorTest
{
OperatorTest()
{
std::cout << "Constructor" << std::endl;
}
~OperatorTest()
{
std::cout << "Destructor" << std::endl;
}
OperatorTest& operator=(const OperatorTest& other)
{
std::cout << "Assignment" << std::endl;
return *this;
}
};
int main()
{
// Operator new[]
OperatorTest* test1 = static_cast<OperatorTest*>(operator new[](sizeof(OperatorTest) * 5)); // Only allocate memory
new (&test1[0]) OperatorTest(); // Calls the constructor by doing a placement new
test1[0].~OperatorTest(); // Calls the destructor
operator delete[](test1);
std::cout << std::endl;
// Operator new
OperatorTest* test2 = static_cast<OperatorTest*>(operator new(sizeof(OperatorTest) * 5)); // Only allocate memory
new (&test2[0]) OperatorTest(); // Calls the constructor by doing a placement new
test2[0].~OperatorTest(); // Calls the destructor
operator delete(test2);
std::cout << std::endl;
{
// How does the STL allocate memory?
std::vector<OperatorTest> test3{ 3 }; // Allocate memory and calls the default constructor
}
std::cout << std::endl;
// Manual new[] / delete[]
OperatorTest* test4 = new OperatorTest[3];
delete[] test4;
return 0;
}
控制台中主要功能的结果是:
析构函数
构造函数
析构函数
构造函数
析构函数
构造函数
全局单操作符和数组操作符似乎都可以为数组分配内存。