我有一个关于使用全局运算符 new、new[]、delete 和 delete[] 的问题(每个问题 1 个帖子,我吸取了教训...)但首先,我将描述情况。
在 Herb Sutter 的 Exceptional C++ 书中的第 12 项 - 编写异常安全代码 - 第 5 部分中,作者使用了以下代码段:
...
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); // Calls the destructor... again
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); // Calls the destructor... again
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;
}
控制台中 main 函数的结果是:
析构函数
构造函数
析构函数
构造函数
析构函数
构造函数
我的问题是:
变量 test1 和 test2 是否正确创建和销毁?我对此感到不安全的一个原因是数组和单个 new/delete 运算符似乎都适用于数组。
我的推理是,即使 STL 似乎也不使用这些运算符。请参阅变量test3
及其输出作为示例。
您对运算符 new 和 delete (及其数组版本)的使用似乎是正确的。
您的代码注释(“再次调用析构函数...”)表明存在误解。您似乎认为全局运算符 delete 不仅会释放内存,还会调用对象的析构函数。不是这种情况。全局运算符 new 和 delete 只分配/释放原始字节,就像 c 函数 malloc 和 free 一样。
从这个意义上说,两个操作符版本(单个与数组)实际上是一样的,只是它们应该匹配,即一个版本分配的内存块必须用相同的版本释放。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句