c++之拷貝構造函數調用時機


test1:

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "這是有默認參數的構造函數!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "這是拷貝構造函數!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一個對象被析構了!\n";
18     }
19 private:
20     int a;
21 };
22 void fuc(Copy_construction t)
23 {
24     cout << "fuc函數!\n";
25 }
26 void play_empty(void)
27 {
28     Copy_construction t1;//調用有默認實參的構造函數
29     Copy_construction t2 = t1;//調用拷貝構造函數
30     Copy_construction t3(t2);//調用拷貝構造函數
31     cout << "_________________\n";
32     fuc(t3);//實參初始化形參,調用拷貝構造函數
33 }
34 int main()
35 {
36     play_empty();
37 
38     cout << "hello world!\n";
39     return 0;
40 }
View Code

運行結果

 test2:

修改fuc函數為引用或者指針類型。

 

 1 void fuc(Copy_construction *t)
 2 {
 3     cout << "fuc函數!\n";
 4 }
 5 
 6 
 7 void fuc(Copy_construction &t)
 8 {
 9     cout << "fuc函數!\n";
10 }
11 
12 /*****引用或者指針類型調用時不會調用拷貝構造函數****/

test3:

匿名對象的出現:

 

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "這是有默認參數的構造函數!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "這是拷貝構造函數!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一個對象被析構了!\n";
18     }
19 private:
20     int a;
21 };
22 Copy_construction fuc(void)
23 {
24     cout << "fuc函數!\n";
25     Copy_construction A;
26     return A;//調用拷貝構造函數,生成匿名對象
27 }//運行到該處,先析構對象A,匿名對象是否析構要看怎么去接
28 //如下所示直接調用fuc()則此時匿名對象會被立即析構
29 void play_empty(void)
30 {
31     fuc();
32 }
33 int main()
34 {
35     play_empty();
36 
37     cout << "hello world!\n";
38     return 0;
39 }

如果直接顯示調用構造函數,要看怎么去接這個函數, Copy_construction(1);調用之后馬上執行析構匿名對象 Copy_construction  T= Copy_construction(1);不會馬上析構還會轉正

test4:

修改fuc函數的返回類型為引用或者指針:

 

 1 Copy_construction *fuc(void)
 2 {
 3     cout << "fuc函數!\n";
 4     Copy_construction A;
 5     return &A;
 6 }
 7 
 8 Copy_construction &fuc(void)
 9 {
10     cout << "fuc函數!\n";
11     Copy_construction A;
12     return A;
13 }
14 
15 
16 /********返回類型為指針或者引用不會調用拷貝構造函數*********/

test5:

改變接匿名對象的方式:

 

 1 #include<iostream>
 2 using namespace std;
 3 class Copy_construction {
 4 public:
 5     Copy_construction(int a = 0)
 6     {
 7         this->a = a;
 8         cout << "這是有默認參數的構造函數!\n";
 9     }
10     Copy_construction(const Copy_construction &obj)
11     {
12         cout << "這是拷貝構造函數!\n";
13         a = obj.a;
14     }
15     ~Copy_construction()
16     {
17         cout << "一個對象被析構了!\n";
18     }
19 private:
20     int a;
21 };
22 Copy_construction fuc(void)
23 {
24     cout << "fuc函數!\n";
25     Copy_construction A;
26     return A;//調用拷貝構造函數,產生匿名對象
27 }//析構對象A,根據下面代碼的接匿名對象的方式,
28 //此時匿名對象不僅不會馬上析構,還會轉正成為對象B
29 //從c++設計哲學上來說,這也是提高效率的一種方式,這樣的設計是合理的,因為你想創建對象B,我就不用再新開辟內存了,直接用之前的匿名對象代替
30 void play_empty(void)
31 {
32     Copy_construction B=fuc();//這里不會調用拷貝構造函數,匿名對象直接轉正了 33     cout << "匿名對象轉正!\n";
34 }
35 int main()
36 {
37     play_empty();
38 
39     cout << "hello world!\n";
40     return 0;
41 }

test6:

再改變接匿名對象的方式,重寫play_empty()函數:

 

void play_empty(void)
{
    Copy_construction B;
    B= fuc();
    cout << "匿名對象不會轉正!\n";
}


//如上所示代碼,此時對象B會開辟內存,在用返回的匿名對象賦值給B,將會在賦值完成之后立即析構匿名對象,這個時候匿名對象不會轉正。

summary:以下情況會調用拷貝構造函數

1.直接初始化和拷貝初始化時

2.將一個對象作為實參傳遞給一個非引用或非指針類型的形參時

3.從一個返回類型為非引用或非指針的函數返回一個對象時

4.用花括號列表初始化一個數組的元素或者一個聚合類(很少使用)中的成員時。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM