天天看點

構造函數,複制構造函數和析構函數

這些函數在網上很容易就可以查到定義和寫法,這裡就不贅述了。令人感興趣的是這些函數什麼時候執行, 特别是複制構造函數和析構函數。

用編寫的一段(很醜的)代碼來說明。

#include<iostream>
#include<cstdio>
#include<cmath>

class Point
{
private:
	/* data */
	double x, y ; 
	friend Point& __doa(Point *ths, const Point& p) ; 

public:
	Point(double x=0, double y=0)
	: x(x), y(y)
	{
		std::cout<<"Creating a Point...\n" ; 
	}
	Point (const Point& obj){
		*this = obj ; 
		std::cout<<"Copying a Point...\n" ; 
	}
	~Point(){
		std::cout<<"Deleting a Point...\n" ; 
	}

	double get_x() const {return x;}
	double get_y() const {return y;}
};

// Point&
// __doa(Point *ths, const Point& p ){
// 	ths->x = p.x ; 
// 	ths->y = p.y ;
// 	return *ths ; 
// }

// Point&
// Point::operator = (const Point& p){
// 	return __doa(this, p) ; 
// }


double dist(Point A, Point B) {
		// 傳回A和B的euclid距離
		double dist_x = A.get_x() - B.get_x() ; 
		double dist_y = A.get_y() - B.get_y() ;
		return sqrt(dist_x*dist_x + dist_y*dist_y) ; 
}

class Circle
{
private:
	/* data */
	Point c ; 
	double r ; 
public:
	Circle(Point c, double r=0)
	: c(c), r(r) 
	{
		std::cout<<"Creating a Circle...\n" ; 
	}
	Circle(const Circle& obj){
		*this = obj ; 
		std::cout<<"Copying a Circle...\n" ; 
	}
	~Circle(){
		std::cout<<"Deleting a Circle...\n" ; 
	}
	Point get_c() const {return c ; }
	double get_r() const {return r; } 
};

bool is_intersect(Circle O1,Circle O2){
	std::cout<<"\n" ; 
	Point c1, c2 ; 
	c1 = O1.get_c() ; 
	c2 = O2.get_c() ; 
	return O1.get_r() +O2.get_r() > dist(c1, c2) ; 
}

int main(){
	Point A(1,0), B(0,1) ;
	std::cout<<"\n" ; 
	std::cout<<dist(A,B)<<"\n";  
	std::cout<<"\n" ; 
	Circle C1(Point(1,0), 2), C2(Point(4,0), 1.2);
	std::cout<<"\n" ; 
	std::cout<<is_intersect(C1, C2)<<"\n" ;  
	std::cout<<"\n" ; 
	C1.get_c() ; 
	std::cout<<"\n" ; 
	return 0 ; 
}
           

輸出資訊:

# 建立A和B
Creating a Point... 
Creating a Point...
# dist建立形參并且銷毀
Copying a Point...
Copying a Point...
1.41421
Deleting a Point...
Deleting a Point...
#建立Circle的時候,首先建立臨時的Point, 然後通過copy複制建立Circle的c, 建立Circle,最後删掉臨時的Point
Creating a Point...
Copying a Point...
Creating a Circle...
Deleting a Point...
Creating a Point...
Copying a Point...
Creating a Circle...
Deleting a Point...
# is_intersect先建立形參Circle的c,然後通過copy複制建立形參
Creating a Point...
Copying a Circle...
Creating a Point...
Copying a Circle...
# 建立c1,c2, 使用函數get_c 會copy一個執行個體出來,然後傳回,删掉。然後給dist傳參,這時候要建立形參,用完删掉。删掉c1,c2. 最後删掉O1, O2(當然删掉Circle之後要把c也删掉). 
Creating a Point...
Creating a Point...
Copying a Point...
Deleting a Point...
Copying a Point...
Deleting a Point...
Copying a Point...
Copying a Point...
Deleting a Point...
Deleting a Point...
Deleting a Point...
Deleting a Point...
1
Deleting a Circle...
Deleting a Point...
Deleting a Circle...
Deleting a Point...
# 可以看到,調用get_c也會使用複制構造函數
Copying a Point...
Deleting a Point...
# 最後删掉main中建立的執行個體(按照建立時間倒序删除,看來是堆棧)
Deleting a Circle...
Deleting a Point...
Deleting a Circle...
Deleting a Point...
Deleting a Point...
Deleting a Point...
           

從上面的輸出資訊可以發現這麼幾點:

  1. 構造使用了自底向上的順序, 而析構使用了自頂向下的順序。 比如給函數is_intersect傳遞形參的時候, 需要先建立一個Point, 也就是c. 因為copy函數是将所有的屬性進行複制, 而沒有Point這個屬性的話是無法進行的。
  2. 傳遞形參, 建立傳回值的時候, 經常使用到複制構造函數。 比如像dist函數傳遞形參的過程中。 還有get_c函數傳回對象c, 即使隻有簡單的一條語句, 也建立了一個新的對象。
  3. 從函數中退出的時候, 本地産生的對象都會被析構, 釋放記憶體。

下面的代碼段是給函數盡可能加上引用之後的形式, 為了進行比較, 也輸出了相應的資訊。

#include<iostream>
#include<cstdio>
#include<cmath>

class Point
{
private:
	/* data */
	double x, y ; 

public:
	Point(const double& x=0, const double& y=0)
	: x(x), y(y)
	{
		std::cout<<"Creating a Point...\n" ; 
	}
	Point (const Point& obj){
		*this = obj ; 
		std::cout<<"Copying a Point...\n" ; 
	}
	~Point(){
		std::cout<<"Deleting a Point...\n" ; 
	}

	double get_x() const {return x;}
	double get_y() const {return y;}
};



double dist(const Point& A,const Point& B) {
		// 傳回A和B的euclid距離
		double dist_x = A.get_x() - B.get_x() ; 
		double dist_y = A.get_y() - B.get_y() ;
		return sqrt(dist_x*dist_x + dist_y*dist_y) ; 
}

class Circle
{
private:
	/* data */
	Point c ; 
	double r ; 
public:
	Circle(const Point& c, const double& r=0)
	: c(c), r(r) 
	{
		std::cout<<"Creating a Circle...\n" ; 
	}
	Circle(const Circle& obj){
		*this = obj ; 
		std::cout<<"Copying a Circle...\n" ; 
	}
	~Circle(){
		std::cout<<"Deleting a Circle...\n" ; 
	}
	Point get_c() const {return c ; }
	double get_r() const {return r; } 
};

bool is_intersect(const Circle& O1,const Circle& O2){
	std::cout<<"\n" ; 
	return O1.get_r() +O2.get_r() > dist(O1.get_c(), O2.get_c()) ; 
}

int main(){
	Point A(1,0), B(0,1) ;
	std::cout<<"\n" ; 
	std::cout<<dist(A,B)<<"\n";  
	std::cout<<"\n" ; 
	Circle C1(Point(1,0), 2), C2(Point(4,0), 1.2);
	std::cout<<"\n" ; 
	std::cout<<is_intersect(C1, C2)<<"\n" ;  
	std::cout<<"\n" ; 
	C1.get_c() ; 
	std::cout<<"\n" ; 
	return 0 ; 
}
           
Creating a Point...
Creating a Point...

1.41421

Creating a Point...
Copying a Point...
Creating a Circle...
Deleting a Point...
Creating a Point...
Copying a Point...
Creating a Circle...
Deleting a Point...


Copying a Point...
Copying a Point...
Deleting a Point...
Deleting a Point...
1

Copying a Point...
Deleting a Point...

Deleting a Circle...
Deleting a Point...
Deleting a Circle...
Deleting a Point...
Deleting a Point...
Deleting a Point...
           

傳遞引用可以減少很多不必要的構造, 節省記憶體空間, 同時也提高效率。