構造函數、複製構造函數、賦值運算符的調用

構造函數、複製構造函數、賦值運算符的調用

結合下面的例子來討論三者的調用順序

#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
	Foo() {
		cout << "Foo constructor" << endl;
	}
	Foo(const Foo&) {
		cout << "Foo copy constructor" << endl;
	}
	Foo& operator= (const Foo&) {
		cout << "Foo operator =" << endl;
		return *this;
	}
	~Foo() {
		cout << "Foo destructor" << endl;
	}
};
int f(Foo) {
	return 0;
}
int g(const Foo&) {
	return 0;
}
Foo h() {
	Foo foo;
	return foo;
}
int main(void) {
	Foo vf1; //1
	f(vf1);//2
	g(vf1);//3
	Foo vf2 = vf1;//4
	vf2 = h();//5
	Foo *pf = new Foo();//6
	delete pf;//7
	vector<Foo> vecf(3);//8
	return 0;
}
  • 1:調用無參構造函數,故:Foo constructor。
  • 2:向函數f傳入剛纔構造的對象vf1,函數結束值vf1要銷燬。故:Foo copy constructor,Foo destructor
  • 3:由於g函數的形參是引用,故不會調用構造函數
  • 4:由於定義對象,並對此對象用產生的對象進行復制(建立一個新的對象,並用另外一個對象進行初始化),故:Foo copy constructor
  • 5:若編譯器不做優化,執行結果:h函數先創建對象,即Foo constructor;返回此對象時,故會創建臨時對象,並對此對象進行復制,即Foo copy constructor;執行完以後,h函數結束作用域,foo對象銷燬,即Foo destructor;由於只是賦值,並沒有定義新的對象,調用賦值運算符,即Foo operator =;最後臨時變量的使命完成,進行銷戶;即Foo destructor。而編譯器做優化以後,返回值優化的目的就是爲了省去臨時對象的創建和銷燬的巨大開銷,這種開銷對程序員不可見,但是會潛在對程序性能產生很大影響。執行結果:Foo constructor,Foo operator =,Foo destructor 。返回值優化具體詳細細節見https://blog.csdn.net/hycxag/article/details/82999739
  • 6:堆上new一個Foo對象,即:Foo constructor
  • 7:delete刪除對應new分配的對象,即:Foo destructor
  • 8:當我們聲明一個具有初始長度的類容器的時候,編譯器會自動調用該類的構造函數對容器進行初始化,所以一般會認爲產生3個Foo constructor的輸出。實際上,這裏的過程是首先生成一個臨時對象,然後以該臨時對象爲藍本進行copy,即調用3次複製構造函數將臨時對象複製到容器中的每個元素,這時臨時對象已經完成其使命,因而編譯器調用析構函數將其釋放,即:Foo constructor,Foo copy constructor,Foo copy constructor,Foo copy constructor,Foo destructor
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章