1.C++中, 對於簡單類型的賦值和初始化的區別基本可以忽略
2.當涉及到類或者複雜的數據類型時,問題就變得不那麼簡單了,下面以一個例子來引入話題:
#include <iostream>
using namespace std;
class Point
{
public:
Point(int a=0, int b=0):x(a), y(b){};
~Point(){
};
Point& operator =(const Point &rhs);
int x;
int y;
};
Point& Point::operator =(const Point &rhs)
{
x = rhs.x+1;
y = rhs.y+1;
return *this;
}
int main(void)
{
Point p(1,1);
Point p1 = p; //初始化操作
Point p2;
p2 = p; //賦值操作
cout<<"p1.x = "<<p1.x<<" "<<"p1.y="<<p1.y<<endl;
cout<<"p2.x = "<<p2.x<<" "<<"p2.y="<<p2.y<<endl;
return 0;
}
運行結果如下:
可以看到賦值操作和初始化操作打印的結果,只在賦值操作中調用了重載“=”的函數。
而在初始化中的“=”調用的是默認的構造函數
爲了證實初始化中的“=”調用的是默認的構造函數,我們可以做如下處理:
根據effctive c++條款05描述,定義了一個空類,如果沒有聲明,系統自動會聲明一個默認構造函數,復刻構造函數,析構函數,和一個運算符重載函數。
class Empty{};
就好像你寫下如下代碼:
class Empty{
public :
Empty(){..}
Empty(const Empty&rts){...}
~Empty() {...}
Empty &operator=(const Empty &rts){...}
}
條款06又描述瞭如不想使用編譯器自動生成的函數,就該明確拒絕,具體做法是將相應的成員函數聲明爲private並且不予實現,因此上述的程序可以改成這樣。
#include <iostream>
using namespace std;
class Point
{
public:
Point(int a=0, int b=0):x(a), y(b){};
~Point(){
};
Point& operator =(const Point &rhs);
int x;
int y;
private:
Point(const Point &p);
};
Point& Point::operator =(const Point &rhs)
{
x = rhs.x+1;
y = rhs.y+1;
return *this;
}
int main(void)
{
Point p(1,1);
Point p1 = p; //初始化操作
Point p2;
p2 = p; //賦值操作
cout<<"p1.x = "<<p1.x<<" "<<"p1.y="<<p1.y<<endl;
cout<<"p2.x = "<<p2.x<<" "<<"p2.y="<<p2.y<<endl;
return 0;
}
這個時候就會報錯,因爲需要調用復刻構造函數,但是它沒有實現
tips:有如下來兩種情況,只能用初始化,而不用賦值
1.對於const和reference 類型的成員變量,只能用初始化列表形式
2.類的構造函數需要調用基類的構造函數的時候
構造函數與賦值函數的區別
1.復刻構造函數是一個對象來初始化一塊內存區域,這塊內存就是新對象的內存區
2.復刻構造函數式複製指針對象,賦值函數是引用指針對象
3.實現方式不一樣,復刻構造函數首先是一個構造函數,它調用的時候好似通過參數傳進來的那個對象來初始化一個對象,賦值函數就是一個已經初始化的對象來進行operator=操作