(原創) 為什麼C++須重新定義Copy Control? (C/C++)
C#、Java都沒有Copy Control,為什麼C++需要有Copy Control呢?
C++是個Hybrid語言,除了built-in type和Class type外,還有個其他語言都沒有的歷史產物:pointer,pointer的用途很多,其中一個用途是因為Dynamic Allocation,而且這種由Dynamic Allocation產生的pointer有幾個特點,第一就是他存的是Memory Address不是Data,所以Copy Constructor和Assignment Operator會有問題,第二就是須delete才會消失,不會隨著object out of scope而消失,有static的味道,所以必須自己在Destructor處理。C#、Java因為沒有pointer,因此不需手動處理Copy Constructor和Assignment Operator,但C#、Java雖有Garbage Collection,但C#仍有Destructor,主要是為了處理非Managed的Resource,如File Handler,Database Connection,但Java已經沒有Destructor了。
回到主題,C++的Copy Contructor和Assignment Operator有什麼問題呢?由Compiler所synthesized的程式,只會將pointer加以複製,很顯然最後指向的結果仍是同一份,這樣就沒有達到Copy的意義了,所以我們得自己重新定義Copy Constructor和Assignment Operator。至於Destructor,因為須手動delete,所以Destructor也必須重新定義。換言之,只要Data Member有用到pointer,也就是動態資料結構時,Copy Constructor、Assignment Operator、Destructor就必須重新定義。
以下範例Demo如何撰寫Copy Control處理單一動態資料和動態陣列。
/* 2
(C) OOMusou 2007 http://oomusou.cnblogs.com3
4
Filename : CopyControl.cpp5
Compiler : Visual C++ 8.0 / ISO C++6
Description : Demo how to use Copy Control with dynamic allocation7
Release : 01/15/2007 1.08
*/9
#include <iostream>10

11
using namespace std;12

13
class Foo {14
// Constructor15
public: 16
Foo(int n = 0) : i(n), pi(new int(n)), pia(new int[n]) { cout << "Constructor" << endl; }17

18
public:19
// Copy Constructor20
Foo (const Foo&);21
// Assignment Operator22
Foo& operator=(const Foo&);23
// Destructor24
~Foo();25

26
public:27
int getStaticInt();28
int getDynamicInt();29
int getDynamicArray(int);30
void setDynamicArray(int, int);31

32
private:33
int i; // static int34
int *pi; // dynamic int35
int *pia; // dynamic int array36
};37

38
// Synthesized Copy Constructor 39
/*40
Foo::Foo(const Foo& foo) {41
this->i = foo.i;42
this->pi = foo.pi; // Error!! just copy pointer43
this->pia = foo.pia; // Error!! just copy pointer44
}45
*/46

47
// Correct Copy Constructor48
Foo::Foo (const Foo& foo) {49
this->i = foo.i;50

51
this->pi = new int(*foo.pi);52

53
this->pia = new int[foo.i];54
for(int n = 0; n != this->i; ++n)55
this->pia[n] = foo.pia[n];56

57
cout << "Copy Constructor" << endl;58
}59

60
// Synthesized Assignment Operator61
/*62
Foo& Foo::operator=(const Foo& foo) {63
this->pstring = foo.pstring; // error!! just copy pointer64
this->i = 0;65
this->d = 0.0;66
return *this; 67
}68
*/69

70
// Correct Assignment Operator71
Foo& Foo::operator=(const Foo& foo) {72
this->i = foo.i;73

74
*this->pi = *foo.pi;75

76
/*while(this->pia < this->pia + foo.i)77
*(this->pia++) = *(foo.pia++);*/78

79
for(int n = 0; n != this->i; ++n)80
this->pia[n] = foo.pia[n];81

82
cout << "Assign Operator" << endl;83

84
return *this; 85
}86

87
// Destructor88
Foo::~Foo() {89
// delete dynamic int90
delete this->pi; 91
// delete dynamic int array92
delete [] this->pia;93

94
cout << "Destructor" << endl;95
}96

97
int Foo::getStaticInt() {98
return this->i;99
}100

101
int Foo::getDynamicInt() {102
return *this->pi;103
}104
105
int Foo::getDynamicArray(int n) {106
return this->pia[n];107
}108

109
void Foo::setDynamicArray(int n, int val) {110
if (n >= 0 && n < this->i) 111
this->pia[n] = val;112
}113

114
int main() {115
Foo foo1;116
cout << foo1.getStaticInt() << endl;117
cout << foo1.getDynamicInt() << endl;118

119
Foo foo2(3);120
cout << foo2.getStaticInt() << endl;121
cout << foo2.getDynamicInt() << endl;122

123
for(int n = 0; n != 3; ++n) 124
foo2.setDynamicArray(n, n+1);125

126
cout << foo2.getDynamicArray(0) << endl;127

128
Foo foo3(foo2); // foo3's Copy Constructor129
Foo foo4 = foo2; // Syntax sugar!! foo4's Copy Constructor130

131
Foo foo5(3);132
foo5 = foo3; // foo5's Assignment Operator133
cout << foo5.getDynamicArray(1) << endl;134
}
執行結果
Constructor
0
0
Constructor
3
3
1
Copy Constructor
Copy Constructor
Constructor
Assign Operator
2
Destructor
Destructor
Destructor
Destructor
Destructor


Foo(
浙公网安备 33010602011771号