iT邦幫忙

1

請問C++中用initializer list初始化和直接賦值的差別?

  • 分享至 

  • xImage

想請問在C++的類別中:

  1. 用initializer list初始化成員變數,如下圖Test1
  2. 將成員變數直接賦值(不是問constructor喔),如下圖Test2

這兩種寫法有什麼差別呢?

https://ithelp.ithome.com.tw/upload/images/20230123/20151787Yw5l6hcQIE.png

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
JamesDoge
iT邦高手 1 級 ‧ 2023-01-26 00:49:22
最佳解答

主要的差別在於初始化的時機不同。

  • Test1:成員變數的初始化和賦值是在類別的 constructor 中進行的,這保證了成員變數在使用之前一定已經被正確初始化。
  • Test2:當你建立類別的物件時,不需要再次初始化成員變數,因為它們已經在類別定義時被初始化過了。

另外一個差別是,使用initializer list初始化成員變數需要在每個constructor中都需要手動初始化,而直接賦值的方式只需要在類別定義時指定一次即可。

補充:
Test2 類別中的 x、y、z 成員變數在類別定義時就已經被初始化為 10 了。
當你建立 Test2 的物件時,不需要再次初始化 x、y、z 成員變數,因為它們已經在類別定義時被初始化過了。

而 Test1 情況下,每個成員變數在建構子建立類別物件時,才會被初始化和賦值。

看更多先前的回應...收起先前的回應...
jeffeux iT邦新手 4 級 ‧ 2023-01-26 03:27:19 檢舉

弱弱問一句,原來可以這樣操作嗎?

#include <iostream>

class Test1 {
  public:
    int x;
    int &y;
    const int z;
    
    Test1(): 
      x(10),
      y(x),  // <-- 原來可以這樣操作嗎?
      z(10)
    {}
};

class Test2 {
  public:
    int x = 10;
    int &y = x;
    const int z = 10;
};

int main() {
    Test1 test1;
    std::cout << test1.y << std::endl;

    return 0;
}
Fylax iT邦新手 5 級 ‧ 2023-01-28 11:25:41 檢舉

不太理解您第二點說的:
"Test2成員變數的初始化和賦值是在類別定義時進行"

非靜態的成員變數不是都應該在建立物件時才初始化和賦值嗎?
而類別定義應是載入時會預先分配記憶體(您的意思是Test2的物件在此時還未建立就會進行初始化和賦值嗎?)

還是我誤解了什麼? (抱歉,我不太了解c++底層的運作XD)

https://ithelp.ithome.com.tw/upload/images/20230128/20151787EnAzPpgNIT.png
https://ithelp.ithome.com.tw/upload/images/20230128/20151787YsWDsNtLny.png
https://ithelp.ithome.com.tw/upload/images/20230128/20151787dZMRHgElEx.png
(t2是在物件建立時才初始化和賦值)

JamesDoge iT邦高手 1 級 ‧ 2023-01-28 12:28:11 檢舉

造成你的誤會,已更新補充

Fylax iT邦新手 5 級 ‧ 2023-01-28 22:08:34 檢舉

感謝,我大致理解了。

另外再請問一下,為什麼像是Test2這樣的寫法較少看到有人使用呢?(如果是在建立物件時不需傳入初值的情況下)使用constructor會比直接賦值多出什麼好處?

JamesDoge iT邦高手 1 級 ‧ 2023-01-29 04:35:18 檢舉

如果成員變數需要一些特殊的初始化過程,比如計算初始值或者某些其他邏輯,則不能使用Test2這種方式初始化

舉例來說,假設有一個類別叫做 "String",裡面有一個成員變數 "str",用來儲存字串。如果想要在建立物件時將str初始化為某個字串的反轉版本,那麼就不能使用Test2這種方式初始化。因為在類別定義時無法執行反轉字串的邏輯.

假設您有一個類別叫做 "BankAccount",它有一個成員變數 "balance",並且您需要在建立物件時檢查賬戶餘額是否足夠,如果不足則賦值為0。在這種情況下,您不能使用Test2的寫法,因為您需要在建立物件時檢查餘額並賦值。

所以通常都使用constructor來初始化成員變數。

Fylax iT邦新手 5 級 ‧ 2023-01-29 23:04:17 檢舉

了解,謝謝!

我要發表回答

立即登入回答