位拷貝拷貝的是地址,而值拷貝則拷貝的是內容。如果定義兩個String對象A和B。A.m_data和B.m_data分別指向一段區域,A.m_data="windows",B.m_data=“linux";
如果未重寫賦值函數,將B賦給A;則編譯器會默認進行位拷貝,A.m_data=B.m_data
則A.m_data和B.m_data指向同一塊區域,雖然A.m_data指向的內容會改變成"linux",但是這樣容易出現這些問題:
(1):A.m_data原來指向的內存區域未釋放,造成內存泄露。
(2):A.m_data和B.m_data指向同一塊區域,任何一方改變都會影響另一方
(3):當對象被析構時,B.m_data被釋放兩次。
對於編譯器,如果不主動編寫拷貝函數和賦值函數,它會以“位拷貝”的方式自動生成缺省的函數。
如果重寫賦值函數和拷貝構造函數後,
A.m_data=B.m_data,進行的是值拷貝,會將B.m_data的內容賦給A.m_data,A.m_data還是指向原來的內存區域,但是其內容改變。如:
#include <iostream>
#include <string>
using namespace std;
class HowMany {
public:
static int objectCount;
public:
HowMany() { objectCount++; }
static void print(const string& msg = "") {
if(msg.size() != 0) cout << msg << ": ";
cout << "objectCount = "
<< objectCount << endl;
}
~HowMany() {
objectCount--;
print("~HowMany()");
}
};
int HowMany::objectCount = 0;
// Pass and return BY VALUE:
HowMany f(HowMany x) {
x.print("x argument inside f()");
return x;
}
int main() {
HowMany h;
HowMany::print("after construction of h");
HowMany h2 = f(h);
HowMany::print("after call to f()");
}
輸出
after construction of h: objectCount = 1
x argument inside f(): objectCount = 1
~HowMany(): objectCount = 0
after call to f(): objectCount = 0
~HowMany(): objectCount = -1 //同一塊區域被析構兩次
~HowMany(): objectCount = -2