C++ 副函式的引數寫const 的疑問

某次在看C++課本裡看到const代表你不能修改const 後面的變數

但我又看到以下程式碼

class Pixel{

private:

int x, y;

public:

Pixel(int a, int b){

x = a; y = b;

cout<<“Normal Constructor”<<endl;

}

};

void welcome(const Pixel& p)

{

//一堆程式碼

}

int main()

{

Pixel p1(3,4);

welcome(p1);

return 0;

}

welcome(const Pixel& p) 這個成員函式 &p代表call by reference

p修改 那原本p1也會跟著修改

但是前面有加const,所以不能修改p跟p1

我要問的是為何還要寫const Pixel &p

寫(Pixel p)不是一樣的意思嗎?

使用&p的用意就是要修改在主程式的p1

前面卻加const使我們不能修改p1

當初寫Pixel p不就好了?既不會修改p1也不用這麼多此一舉寫const 跟&

3 個解答

評分
  • 其威
    Lv 7
    6 年前
    最佳解答

    你的問題其實是兩個問題:

    1. 為什麼要傳 &?

    2. 為什麼要傳 const &?

    === 分隔線 ===

    先回答「為什麼要傳 &」:

    C++ 預設是以 by-value 傳參數,如果你的參數是個很大的 object(或是 copy c-tor 的成本很高),會造成不必要的 overhead。

    舉例來說,我今天有個函式:

    void say_hello(std::string const & name)

    {

    std::cout << "Hello, " << name << std::endl;

    }

    如果沒有這個 &,你的程式會把參數複製一份傳進去。

    這在內建型別(如 int、double、*... 等等)上感覺不出太多差別,可是如果你傳的東西是像此例中的物件,那麼他可能要複製很多東西。

    例如你的 name 可能是個很長的字串(幾 MB 這樣...),那編譯器就要複製幾 MB 的東西進去。

    如果你只呼叫個一兩次當然沒差,可是當需要呼叫成千上萬次的時候,就會感覺出差異。

    沒有 & 要複製幾 MB,有 & 只會傳個記憶體位置。

    那你可能又會問說「反正我的 Pixel class 裡面只有兩個 int,複製成本應該不會很高,用 & 傳有意義嗎?」

    答案是,只要你的 class 比 * 還大,就有意義。

    === 分隔線 ===

    第二個問題,「為什麼要用 const 傳參數?」

    我用 const 傳參數,主要有下面兩個理由(可能還有別的一時想不起來):

    1. 避免函式不小心修改到變數內容

    例如我有個函式,我很確定參數內容不應該被修改,這時候我會把參數宣告成 const &,可以避免不小心修改到。

    舉例:

    std::string score_to_grade(int const & score)

    {

    if (score == 0) return "Orz"; // (1)

    else if (score < 60) return "F";

    else if (score < 70) return "D";

    else if (score < 80) return "C";

    else if (score < 90) return "B";

    else if (score < 100) return "A";

    else if (score == 100) return "S"; // (2)

    else return "ERROR";

    }

    如果不小心把 == 打成 =(例如 (1) 與 (2) 兩處),編譯器就會抓到我嘗試修改 const 變數。

    2. 避免傳入參數是 const 時型態不符有時候我會有一些常數是不想被修改的,例如:

    static std::string const AUTHOR = "Palatis";

    如果有個函式長這樣:

    void say_hello(std::string & name)

    {

    std::cout << "Hello, " << name << std::endl;

    }

    為了避免不必要的複製成本,我用 by-reference 的方式傳參數。

    但是這樣一來,我如果想 say_hello(AUTHOR) 會型態不符,因為 AUTHOR 是個 const 變數,可是 say_hello() 需要 non-const 參數。

    所以 say_hello() 的原型應該是:

    void say_hello(std::string const & name);

    那麼這個函式在 name 參數是 const 或 non-const 的狀況都適用。

  • 匿名使用者
    6 年前

    到下面的網址看看吧

    ▶▶http://candy5660601.pixnet.net/blog

  • 6 年前

    : p修改 那原本p1也會跟著修改

    p是const, 為何說p修改, 你要怎麼修改p?

    : 但是前面有加const,所以不能修改p跟p1

    但是你寫的程式只有p是const, 而p1不是const.

    : 我要問的是為何還要寫const Pixel &p

    : 寫(Pixel p)不是一樣的意思嗎?

    前者是call by reference, 是p1本身傳入函式,

    後者是call by value, 是複製p1成另一個物件再傳入函式.

    意思不一樣.

    : 既不會修改p1也不用這麼多此一舉寫const 跟&

    因為"複製"是多此一舉, 所以傳const &較好.

還有問題?馬上發問,尋求解答。