同類物件之間可以通過賦值運算子
=
互相賦值。如果沒有經過過載,
=
的作用就是把左邊的物件的每個成員變數都變得和右邊的物件相等,即執行逐個位元組拷貝的工作,這種拷貝叫作“淺拷貝”。
有的時候,兩個物件相等,從實際應用的含義上來講,指的並不應該是兩個物件的每個位元組都相同,而是有其他解釋,這時就需要對
=
進行過載。
上節我們定義了 String 類,並過載了
=
運算子,使得 char * 型別的字串可以賦值給 String 類的物件。完整程式碼如下:
#include <iostream>
#include <cstring>
using namespace std;
class String {
private:
char * str;
public:
String() :str(NULL) { }
const char * c_str() const { return str; };
String & operator = (const char * s);
~String();
};
String & String::operator = (const char * s)
//過載"="以使得 obj = "hello"能夠成立
{
if (str)
delete[] str;
if (s) { //s不為NULL才會執行拷貝
str = new char[strlen(s) + 1];
strcpy(str, s);
}
else
str = NULL;
return *this;
}
String::~String()
{
if (str)
delete[] str;
};
int main()
{
String s;
s = "Good Luck,"; //等價於 s.operator=("Good Luck,");
cout << s.c_str() << endl;
// String s2 = "hello!"; //這條語句要是不注釋掉就會出錯
s = "Shenzhou 8!"; //等價於 s.operator=("Shenzhou 8!");
cout << s.c_str() << endl;
return 0;
}
對於上面的程式碼,如果讓兩個 String 物件相等(把一個物件賦值給另一個物件),其意義到底應該是什麼呢?是兩個物件的 str 成員變數都指向同一個地方,還是兩個物件的 str 成員變數指向的記憶體空間中存放的內容相同?如果把 String 物件理解為存放字串的物件,那應該是後者比較合理和符合習慣,而前者不但不符合習慣,還會導致程式漏洞。
按照上面程式碼中 String 類的寫法,下面的程式片段會引發問題:
String s1, s2;
s1 = "this";
s2 = "that";
s2 = s1;
執行完上面的第 3 行後,s1 和 s2 的狀態如圖 1 (a) 所示,它們的 str 成員變數指向不同的儲存空間。
圖1:淺拷貝導致的錯誤