亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

請問 為什么C+11類初始化器不能使用括號?

請問 為什么C+11類初始化器不能使用括號?

C++
繁星coding 2019-08-02 11:03:12
為什么C+11類初始化器不能使用括號?例如,我不能這樣寫:class A{     vector<int> v(12, 1);};我只能這樣寫:class A{     vector<int> v1{ 12, 1 };     vector<int> v2 = vector<int>(12, 1);};C+11語言設計的不同之處在于什么?
查看完整描述

2 回答

?
鴻蒙傳說

TA貢獻1865條經驗 獲得超7個贊

這一選擇背后的理由在相關的提案非靜態數據成員初始化器 :

在科納提出的關于識別資料范圍的問題:

在2007年9月在科納舉行的核心工作組討論期間,出現了一個關于初始化程序中標識符的范圍的問題。我們想要允許類作用域與前向查找的可能性;還是我們想要求初始化程序在解析后被很好地定義?

想要什么:

類范圍查找的動機是,我們希望能夠將任何內容放入非靜態數據成員的初始化器中,這樣就可以在不顯著改變語義的情況下將其放入mem初始化程序中(模塊直接初始化與復制初始化):

int x();struct S {
    int i;
    S() : i(x()) {} // currently well-formed, uses S::x()
    // ...
    static int x();};struct T {
    int i = x(); // should use T::x(), ::x() would be a surprise
    // ...
    static int x();};

問題1:

不幸的是,在解析聲明時,這使得“(表達式-列表)”形式的初始化器變得模糊不清:

   struct S {
        int i(x); // data member with initializer
        // ...
        static int x;
    };

    struct T {
        int i(x); // member function declaration
        // ...
        typedef int x;
    };

一個可能的解決方案是依賴現有的規則,如果聲明可以是對象或函數,那么它就是一個函數:

 struct S {
        int i(j); // ill-formed...parsed as a member function,
                  // type j looked up but not found
        // ...
        static int j;
    };

類似的解決方案是應用另一條現有規則,目前僅在模板中使用,即如果T可以是類型或其他類型,那么它就是另一種類型;如果我們真正指的是類型,則可以使用“type Name”:

struct S {
        int i(x); // unabmiguously a data member
        int j(typename y); // unabmiguously a member function
    };

這兩種解決方案都引入了許多可能被許多用戶誤解的微妙之處(如comp.lang.c+中關于為什么“intI();”at塊作用域不聲明默認初始化的int)的許多問題所證明的那樣。

本文提出的解決方案是只允許“=初始化-子句”和“{初始化-列表}”形式的初始化程序。..,這解決了例如:

HashingFunction hash_algorithm{"MD5"};

在這里,我們不能使用=表單,因為HasningFunction的構造函數是顯式的。在特別棘手的情況下,可能需要兩次提到一個類型。考慮:

   vector<int> x = 3; // error:  the constructor taking an int is explicit
   vector<int> x(3);  // three elements default-initialized
   vector<int> x{3};  // one element with the value 3

在這種情況下,我們必須使用適當的表示法在這兩種選擇之間進行選擇:

vector<int> x = vector<int>(3); // rather than vector<int> x(3);vector<int> x{3}; // one element with the value 3

問題2:

另一個問題是,由于我們不建議修改初始化靜態數據成員的規則,添加靜態關鍵字可能會使格式良好的初始化器不正確:

   struct S {
               const int i = f(); // well-formed with forward lookup
        static const int j = f(); // always ill-formed for statics
        // ...
        constexpr static int f() { return 0; }
    };

問題3:

第三個問題是類范圍查找可能將編譯時錯誤轉換為運行時錯誤:

struct S {
    int i = j; // ill-formed without forward lookup, undefined behavior with
    int j = 3;};

(除非被編譯器捕獲,否則我可能會使用未定義的值j)。

建議:

CWG在科納進行了6比3的民意調查,支持類范圍查找;這也是本文所建議的,非靜態數據成員的初始化器僅限于“=initiators-子句”和“{initiator-list}”表單。

我們認為:

問題1:這個問題不會發生,因為我們沒有提出()表示法。=和{}初始化符號不受此問題的影響。

問題2:添加靜態關鍵字會產生許多差異,這是其中最小的差異。

問題3:這不是一個新問題,而是與構造函數初始化器已經存在的初始化順序相同的問題。




查看完整回答
反對 回復 2019-08-04
  • 2 回答
  • 0 關注
  • 358 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號