一個對象賦值給自己的時候就發(fā)生了一次自賦值:
class Widget { ... };
Widget w;
...
w = w; // assignment to self
這看起來很愚蠢,但它是合法的,所以應(yīng)該確信客戶會這樣做。另外,賦值并不總是那么容易辨別。例如,
a[i] = a[j]; // potential assignment to self
如果 i 和 j 有同樣的值就是一個自賦值,還有
*px = *py; // potential assignment to self
如果 px 和 py 碰巧指向同一個東西,這也是一個自賦值。這些很不明顯的自賦值是由別名(有不止一個方法引用一個對象)造成的。通常,當(dāng)引用或者指針指向相同類型的多個對象時,對這些引用和指針進(jìn)行操作的代碼需要考慮到那些對象可能是相同的。實(shí)際上,如果兩個對象來自同一個繼承體系,甚至不需要公開聲明,它們就是相同類型的,因?yàn)橐粋€基類的引用或者指針也能夠引用或者指向派生類類型的對象:
class Base { ... };
class Derived: public Base { ... };
void doSomething(const Base& rb, // rb and *pd might actually be
Derived* pd); // the same object
如果你遵循 Item 13 和14 的建議,你應(yīng)該總是使用對象來管理資源,而且你應(yīng)該確保那些資源管理對象(resource-managing objects)被拷貝時行為良好。如果是這種情況,你的賦值運(yùn)算符在你沒有考慮自拷貝的時候可能也是自賦值安全(self-assignment-safe)的。但是,如果你試圖自己管理資源,無論如何(如果你寫一個資源管理類(resource-managing class),你當(dāng)然不得不做),你可能會落入在你使用完一個資源之前就已意外地將它釋放的陷阱。例如,假設(shè)你創(chuàng)建了一個類,它持有一個指向動態(tài)分配 bitmap 的指針:
class Bitmap { ... };
class Widget {
...
private:
Bitmap *PB; // ptr to a heap-allocated object
};
class Widget { ... };
Widget w;
...
w = w; // assignment to self
這看起來很愚蠢,但它是合法的,所以應(yīng)該確信客戶會這樣做。另外,賦值并不總是那么容易辨別。例如,
a[i] = a[j]; // potential assignment to self
如果 i 和 j 有同樣的值就是一個自賦值,還有
*px = *py; // potential assignment to self
如果 px 和 py 碰巧指向同一個東西,這也是一個自賦值。這些很不明顯的自賦值是由別名(有不止一個方法引用一個對象)造成的。通常,當(dāng)引用或者指針指向相同類型的多個對象時,對這些引用和指針進(jìn)行操作的代碼需要考慮到那些對象可能是相同的。實(shí)際上,如果兩個對象來自同一個繼承體系,甚至不需要公開聲明,它們就是相同類型的,因?yàn)橐粋€基類的引用或者指針也能夠引用或者指向派生類類型的對象:
class Base { ... };
class Derived: public Base { ... };
void doSomething(const Base& rb, // rb and *pd might actually be
Derived* pd); // the same object
如果你遵循 Item 13 和14 的建議,你應(yīng)該總是使用對象來管理資源,而且你應(yīng)該確保那些資源管理對象(resource-managing objects)被拷貝時行為良好。如果是這種情況,你的賦值運(yùn)算符在你沒有考慮自拷貝的時候可能也是自賦值安全(self-assignment-safe)的。但是,如果你試圖自己管理資源,無論如何(如果你寫一個資源管理類(resource-managing class),你當(dāng)然不得不做),你可能會落入在你使用完一個資源之前就已意外地將它釋放的陷阱。例如,假設(shè)你創(chuàng)建了一個類,它持有一個指向動態(tài)分配 bitmap 的指針:
class Bitmap { ... };
class Widget {
...
private:
Bitmap *PB; // ptr to a heap-allocated object
};