代碼如下
#include <iostream>class A{public: A():a(0),b(0){std::cout<<"調用第一個構造函數"<<std::endl;} A(int x):a(x),b(x+1){std::cout<<"調用第二個構造函數"<<std::endl;} ~A(){std::cout<<"調用析構函數"<<std::endl;} int geta(){ return a; } int getb(){ return b; }PRivate: int a; int b;};int main(){ A test; test = A(5); std::cout<<test.geta()<<std::endl; std::cout<<test.getb()<<std::endl; return 0;}經過編譯和運行之后,結果如下:
調用第一個構造函數 調用第二個構造函數 調用析構函數 5 6 調用析構函數
首先要知道: 一、C++編譯器可以在沒有拷貝構造函數和Operator=這兩個函數的時候可以自動的生成這兩個函數。 二、這兩個函數只能是由按位拷貝的語義,因此是淺拷貝,當有指針成員的時候,它只能拷貝指針的數值,而不能拷貝指針指向的內容。因此這兩個函數僅僅在某些特定的情況下才可能有效的發揮作用。
代碼分析: 在聲明test的時候,調用了第一個構造函數,然后在執行到test=A(5)的時候,調用了第二個構造函數,重點就在這里,這里不是test調用了第二個構造函數,實際是編譯器生成了一個臨時對象,是這個臨時對象調用了第二個構造函數。前面提到了,在沒有自己寫拷貝構造函數和operator=這兩個函數的時候,編譯器會自動生成,這個時候的拷貝都是淺拷貝,編譯器執行A(5)的時候創建了一個臨時的對象,然后通過編譯器自己生成的operator=函數把這個臨時對象的值賦給了test,最后析構這個臨時對象。
這里有個值得注意的地方就是這種采用默認拷貝構造和operator=的拷貝和賦值都是淺拷貝,當有指針的時候應當特別注意不能這樣使用,容易出現問題。 還有就是這中直接調用構造函數的方式,還有可能造成野指針,例如:
A* ptr = &A(5);在臨時對象消失之后,ptr成為了野指針。
如果想要延長臨時對象生存周期,有一種方法是對它進行const引用:
const A& a = A(5);這樣只要a存在,由A(5)產生的臨時對象就會存在。
新聞熱點
疑難解答
圖片精選