1. 程式人生 > 實用技巧 >【C/C++】【類和物件】拷貝建構函式

【C/C++】【類和物件】拷貝建構函式

拷貝建構函式

預設情況下,類物件的拷貝是每個成員變數逐個拷貝;

含義:首先是一個類的建構函式,第一個引數是所屬的類型別的引用,如果還有其他額外引數,那麼這些額外引數必須都有預設值,函式預設引數必須放在函式宣告,除非該函式沒有函式宣告;

作用:需要呼叫的時候,系統自動呼叫

建議

  • 拷貝建構函式第一個引數總是帶const;
  • explicit:拷貝建構函式一般不要宣告成explicit;

成員變數逐個拷貝,由於定義了拷貝建構函式而丟失了作用,或者說自己定義的拷貝建構函式取代了系統預設的每個成員變數逐個拷貝的這種行為;

  • 如果沒有定義拷貝建構函式,編譯器就會幫忙定義一個“合成拷貝建構函式”;
  • 如果是編譯器定義的合成構造拷貝函式,這個合成拷貝建構函式一般也是將引數的成員逐個拷貝到目標物件中;每個成員的型別決定它如何拷貝,如果成員變數是基本型別,就直接把值拷貝過來;如果成員變數是類型別,那麼就會呼叫這個類的拷貝建構函式;
  • 如果自己定義了拷貝建構函式,就取代了系統合成的拷貝建構函式,這時候,必須要在自己的拷貝建構函式中給類成員賦值以免類成員沒有被賦值;
#include <iostream>
using namespace std;
//類定義(類宣告)
class Time
{

public:
    int Hour; //小時
    int Minue; //分鐘
    int Second = 0; //秒鐘

public:
    //建構函式
    Time();
    //...
    //拷貝建構函式
    Time(Time &tmptime, int a = 1);

private:
    //...
};


Time::Time()
{
    std::cout<<"Time::Time()"<<std::endl;
}
Time::Time(Time &tmptime, int a):Hour(tmptime.Hour), Minue(tmptime.Minue), Second(tmptime.Second)
{
    std::cout<<"Time::Time(Time &tmptime, int a)"<<std::endl;
}

int main()
{
    Time myTime; //呼叫預設建構函式,不帶引數的
    Time mytime2 = myTime; //呼叫了拷貝建構函式
    Time mytime3(myTime); //呼叫了拷貝建構函式
    Time mytime4{myTime}; //呼叫了拷貝建構函式
    Time mytime5 = {myTime}; //呼叫了拷貝建構函式
    Time mytime6; //呼叫了無參建構函式
     mytime6 = mytime5; //若類中有常量成員,則不成功

     return 0;
}

其它呼叫拷貝建構函式的情況

呼叫拷貝構造的情況

  1. 將一個物件作為實參傳遞給一個非引用型別的形參也會呼叫了拷貝建構函式;

    #include <iostream>
    using namespace std;
    //類定義(類宣告)
    class Time
    {
    
    public:
        int Hour; //小時
        int Minue; //分鐘
        int Second = 0; //秒鐘
    
    public:
        //建構函式
        Time();
        //...
        //拷貝建構函式
        Time(Time &tmptime, int a = 1);
    
    private:
        //...
    };
    
    
    Time::Time()
    {
        std::cout<<"Time::Time()"<<std::endl;
    }
    Time::Time(Time &tmptime, int a):Hour(tmptime.Hour), Minue(tmptime.Minue), Second(tmptime.Second)
    {
        std::cout<<"Time::Time(Time &tmptime, int a)"<<std::endl;
    }
    void func(Time tmpTime)
    {
        return;
    }
    
    int main()
    {
        Time myTime;
        func(myTime);
    
        return 0;
    }
    
  2. 函式中返回物件

    #include <iostream>
    using namespace std;
    //類定義(類宣告)
    class Time
    {
    
    public:
        int Hour = 0; //小時
        int Minue = 0; //分鐘
        int Second = 0; //秒鐘
    
    public:
        //建構函式
        Time();
        //...
        //拷貝建構函式
        Time(const Time& tmptime);
    
    private:
        //...
    };
    
    
    Time::Time()
    {
        std::cout << "Time::Time()" << std::endl;
    }
    Time::Time(const Time& tmptime) :Hour(tmptime.Hour), Minue(tmptime.Minue), Second(tmptime.Second)
    {
        std::cout << "Time::Time(Time &tmptime, int a)" << std::endl;
    }
    Time func()
    {
        Time tmpTime;
        return tmpTime; //系統產生了臨時物件,呼叫拷貝建構函式
    }
    
    int main()
    {
        Time mytime = func();
    
        //Time myTime;
        //Time myTime2 = myTime;
        return 0;
    }
    
名稱 型別
&tmpTime 0x000000487591fa68 {Hour=0 Minue=0 Second=0 } Time *
名稱 型別
&mytime 0x000000487591fb98 {Hour=0 Minue=0 Second=0 } Time *

二者地址都不一樣,在返回物件的時候,系統會一個臨時物件;