【发布时间】:2013-02-27 15:39:55
【问题描述】:
我有一个 A 类,它在其构造函数中为整数(由类成员说 _pPtrMem 指向)动态分配内存,并在析构函数中释放相同的内存。为了避免浅拷贝,我重载了赋值运算符和拷贝构造函数。赋值运算符重载的广泛使用方式如下:
A& operator = (const A & iToAssign)
{
if (this == & iToAssign) // Check for self assignment
return *this;
int * pTemp = new int(*(iToAssign._pPtrMem)); // Allocate new memory with same value
if (pTemp)
{
delete _pPtrMem; // Delete the old memory
_pPtrMem = pTemp; // Assign the newly allocated memory
}
return *this; // Return the reference to object for chaining(a = b = c)
}
实现相同的另一种方法是
A& operator = (const A & iToAssign)
{
*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
return *this;
}
既然第二个版本比较简单和快速(没有释放,分配内存)为什么没有被广泛使用?有什么我无法弄清楚的问题吗?
此外,我们从赋值运算符中返回一个相同类型的对象用于链接(a = b = c)...所以不是返回 *this 而是返回 iToAssign 对象,因为这两个对象现在应该是相等的?
【问题讨论】:
-
如果你只有一个整数,为什么还要使用指针呢?如果您有动态分配的数组,请考虑改用
std::vector。 -
注意:在版本 1 中,
delete为时过早。应该在当前对象处于稳定状态后进行(否则不提供强异常保证)。在这里它不稳定,因为您在删除后分配给当前对象。你应该std::swap(_pPtrMem, pTemp);delete pTemp;。最好使用复制和交换习语。 -
@LokiAstari 但是分配指针不能抛出异常,没有什么可以出错的。
-
@TorstenRobitzki:但是删除可以抛出(如果被删除的对象有析构函数)。因此,为了保持一致,请在完成更改对象后始终放置删除(这样,如果您稍后修改包含的类型,则无需更改分配中的代码)。但是您对于像
int这样的 POD 类型是正确的,这就是为什么这只是一个评论。 -
@LokiAstari
delete不会为时过早(但不需要进行自分配测试)。如果delete可以抛出,则no 可以安全地实现它;这就是为什么析构函数永远不应该抛出。 (有一些特殊的例外,但其析构函数可能抛出的类永远不应用作另一个类的一部分或放入容器中。)
标签: c++ operator-overloading assignment-operator