搜尋

首頁  >  問答  >  主體

c++11 - const的一些问题(c++primer 第五版)

1.

中文版:

设置一个类型为auto的引用时,初始值中的顶层常量属性依然保留。和往常一样,如果我们给初始值绑定一个引用,则此时的常量就不是顶层常量了。”

英文版:

When we ask for a reference to an auto-deduced type, top-level consts in the initializer are not ignored. As usual, consts are not top-level when we bind a reference to an initializer

怎么理解这段话呢?能否举例说明?

阿神阿神2809 天前768

全部回覆(2)我來回復

  • 天蓬老师

    天蓬老师2017-04-17 11:48:52

    top-level const : const 修飾的是自身
    low-level const : const 修飾的是別人

    什麼叫自身,什麼叫別人? C++ 的世界:

    • POD,類別物件都只能是"自身"
    • 指標可以是自身(指標本身),可以是別人(指向別人)。
    • 引用沒有自身,只能是別人。 (引用是別名)

    所以,有以下幾個規律:

    • 指針,可以是 top-level const,也可以是 low-level const
    • 引用只能是 low-level const

    指針何時是 top-level const,何時是 low-level const,請參考昨天回答的你的另一個問題。
    (const char *是 low-level, char * const 是 top-level.)


    如果上面這堆概念你都搞清楚了的話,我們在來理解一下你引用的話。舉例說明:

    cppconst int ci = 0;
    auto &r1 = ci; // r1 is a const int&
    

    好了,ciconst int,是 top-level const;r1 呢?是 const int&,是引用,引用必然是 low-level const

    所以:

    consts are not top-level when we bind a reference to an initializer

    後半句同意吧?

    再看範例裡面的 r1,請問你可以修改它嗎?你可能會不解,廢話,都加了 const 還能修改?

    那我們來看另一個例子:

    cppconst char * ch = "test";
    ch = "mood"; // ok, const is low-level
    
    char c[4] = "hel";
    char * const cch = c;
    cch = ch; // error! const is top-level
    

    看到了吧,對於指標來說,low-level const 是可以修改的! (對應開始的概念,指針可以是"別人",別人是 const 不影響指針指向另一個人)

    那麼 const int* 可以修改,而 const int& 不能修改,這是由引用本身的概念導致的(一旦初始化無法再次綁定)。
    即,const 引用是 low-level const 的同時,也兼備了 top-level const 的特質,即"自身"無法被修改。

    所以:

    When we ask for a reference to an auto-deduced type, top-level consts in the initializer are not ignored.

    說的是“頂層常數屬性仍然保留”,好好體會一下這裡說的頂層常量屬性的含義。


    綜上所述,結合我給的例子。最簡單的解釋:

    auto &r1 = ci; 發生了什麼事?

    1. 從 top-level const 降成 low-level const.
    2. top-level const 的特質(自身無法修改)依然保留。

    清楚了嗎?

    PS: 為什麼 C++ Primer 提倡多用引用,少用指針,因為指針太過於靈(奇)活(葩)。還是引用比較好駕馭。 。 。

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-17 11:48:52

    這方面教學很多了,我簡單寫下, 如果理解不對,歡迎指正。

    #include <iostream>
    using namespace std;
    
    
    class MyObject{
    private:
        int value;
    public:
        MyObject(){
            this->value = 0;
        }
    
        void foo() {
            cout << "none const obj called" << endl;  //证明调用者是一个非const对象
        }
        void foo() const {
            cout << "const obj called" << endl;   //证明调用者是一个const对象
        }
        MyObject (const MyObject & other){
            this->value = other.value;
        }
    };
    
    int main()
    {
       MyObject obj;
       const MyObject constObj = obj;
       obj.foo();  //输出非const foo
       constObj.foo(); //const foo
       cout<< "*******"<<endl;
       auto auto_without_const = constObj; //auto没有加引用的情况下,即使右边的值有const属性,也被去了
       auto_without_const.foo();
       auto & auto_with_const = constObj; //一旦是引用的时候,就保留下来const属性
       auto_with_const.foo();
    
       auto & const_refer_to_none_const = obj; //右值没有const属性,初始化后也没有
       const_refer_to_none_const.foo();
       return 0;
    }
    

    回覆
    0
  • 取消回覆