1.用同一類型的對象來初始化另一對象需要調用複製建構函式
例1:
class A{public:A(){}A(const A& a){cout<<"copy"<<endl;}};int main(){A a, c;A b = a;//顯式複製建構函式(1)c = a;//賦值函數(2)return 0;}
本例要注意的是(1)和(2)的區別:
複製建構函式也是建構函式的一種。只要是建構函式,就要開闢空間。
(1)在初始化的同時還要完成開闢空間的任務,所以在複製建構函式
(2)在L9已經開闢了空間(變通建構函式),這裡只是賦值
2.複製建構函式可用於傳參或傳回值(僅限於按值傳遞)
例2:
class A{public:A(){}A(const A& a){cout<<"copy"<<endl;}};A Test(A a){return a;}int main(){A a;Test(a);//調用了兩次建構函式,一次傳參,一次是傳回值return 0;}
3.複製建構函式可用於初始化順序容器中的元素,順序容包括vector、list、deque
例3:
class A{int x;public:A(int i):x(i){cout<<"construct "<<i<<endl;}A(const A& a){cout<<"copy"<<endl;}};int main(){list<A> a(10, 5);return 0;}
輸出:
construct 5
copy
copy
copy
copy
copy
copy
copy
copy
copy
copy
先構造一個臨時對象,再把它依次複製到容器中
4.根據元素初始化列表初始化數組元素時也調用複製建構函式
例:
class A{int x;public:A(){cout<<"construct "<<endl;}A(int i):x(i){cout<<"construct "<<i<<endl;}A(const A& a){cout<<"copy"<<endl;}};int main(){cout<<"****Test1****"<<endl;A s1[5];cout<<"****Test2****"<<endl;A s2[5] = {1, 2, 3, 4, 5};cout<<"****Test3****"<<endl;A a(1), b(2), c(3), d(4), e(5);A s[5] = {a, b, c, d, e};return 0;}
輸出結果:
****Test1****
construct
construct
construct
construct
construct
****Test2****
construct 1
construct 2
construct 3
construct 4
construct 5
****Test3****
construct 1
construct 2
construct 3
construct 4
construct 5
copy
copy
copy
copy
copy
分析結果:
Test1:構造
Test2:構造(隱式類型轉換)
Test3:L16是構造L17是複製
5.如果定義了自己的建構函式,系統還是會提供一個預設的複製建構函式
如果定義了自己的複製建構函式,系統不會提供一個預設的建構函式
6.複製建構函式的行為:依次複製每一個非static成員,只是複製內容,稱為淺層複製。
如果類中有指標成員,淺層複製會出錯。需要定義自己的複製建構函式,使用深層複製。
7.如果要禁止複製,可以複製建構函式聲明為私人
如果連友元和成員也要禁止複製,可聲明為私人,且只聲明不定義。
8.iostream類禁止複製,它的複製建構函式是私人的