C++ 速查手冊

9.14 - Copy 建構函數

假設我們有個 Demo 類別,先建立 Demo 型態的變數 d1 ,然後宣告同是 Demo 型態的變數 d2 ,並且直接把 d1 指派給 d2 ,如下

Demo d1(p1);
Demo d2 = d1;

這麼寫是沒問題的,因為 d1 複製給 d2 的過程當中會啟動 copy 建構函數,利用 copy 建構函數完成整個過程,而且就算我們沒有自己寫出 copy 建構函數的話,編譯器也會主動幫我們加上一個。

可是當 Demo 有成員是指標的話會出現一些問題,當我們改變 d2 的指標成員,使用預設的 copy 建構函數會連帶改變 d1 的指標成員 ,這就不會是我們希望的結果了。

因此我們需要自行設計 copy 建構函數,舉一個完整例子如下

#include <iostream>
#include <string>

class Demo {
public:
    Demo(std::string s) {
        std::cout << "constructor" << std::endl;
        a_ptr = new std::string;
        *a_ptr = s;
    }
    
    Demo(const Demo& obj) {
        std::cout << "copy constructor" << std::endl;
        a_ptr = new std::string;
        *a_ptr = *obj.a_ptr;
    }
    
    void set_a(std::string s) {
        *a_ptr = s;
    }
    
    void do_something() {
        std::cout << *a_ptr << std::endl;
    }
    
private:
    std::string *a_ptr;
};

int main() {
    Demo d1("There is no spoon.");
    d1.do_something();
    Demo d2 = d1;
    d2.do_something();
    
    d1.set_a("What's truth?");
    d1.do_something();
    d2.do_something();
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
   https://kaiching.org/
   檔名:u0914.cpp
   功能:示範 C++ 的類別
   作者:張凱慶*/

Copy 建構函數在第 13 行,需要 const參考當參數

Demo(const Demo& obj) {
    std::cout << "copy constructor" << std::endl;
    a_ptr = new std::string;
    *a_ptr = *obj.a_ptr;
}

編譯執行,結果如下

$ g++ u0914.cpp
$ ./a.out
constructor
There is no spoon.
copy constructor
There is no spoon.
What's truth?
There is no spoon.
$

上一頁 9.13 - 巢狀類別
回 C++ 速查手冊首頁
下一頁 9.15 - 解構函數
回 C++ 教材
回程式語言教材首頁