c++11 - const的一些问题(c++primer 第五版)
阿神
阿神 2017-04-17 11:46:52
0
2
766

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

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

阿神
阿神

闭关修行中......

Antworte allen(2)
Peter_Zhu

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 constr1 呢?是 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 提倡多用引用,少用指针,因为指针太过于灵(奇)活(葩)。还是引用比较好驾驭。。。

大家讲道理

这方面教程很多了,我简单写下, 如果理解不对,欢迎指正。

#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;
}
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage