目录:
引言:
最近在看C++ Primer第五版这本书,书中提到了顶层const与底层const的这一概念,以及对应的auto与decltype在识别const时而反映出的不同问题,以及圆括号(),花括号{}在初始化的一些常见的问题。本篇文章相当于自己在看了100多页后的一个对本书的一个我认为难点的或者说新奇点的一个总结。以下只是个人见解,如有错误,欢迎大家与我讨论纠正。
一、顶层const与底层cosnt
我对顶层const的理解就是,限制自己不能改的const就叫做顶层const,限制所指之物不能改的const就叫做底层const,举例:
int i = 0;
int *const p1 = &i; //限制自身(pi)不能修改,顶层const
const int ci = 42; //限制自身(ci)不能修改,顶层const
const int *p2 = &ci; //限制所指之物不能修改,底层const
const int *const p3 = p2; //靠右的是顶层const,最前面的是底层const
const int &r = ci; //引用底层也是指针,所以也理解为所指之物不能被修改,底层const
//const int const *r = &ci; //底层实现
注: 值得注意的是“所指之物”,不仅包含了指针,也包含了引用,因为引用从底层实现来说就是个指针,所以对const &符的const也是个底层const
区分顶层const与底层const的用处
- 一个原因就是对于const限制的变量进行拷贝赋值的问题,这个问题来说,我没有用顶层const与底层const来区分,我看的是拷贝赋值后,有没有对原有的const产生矛盾,这里我不在过多的叙述了,大家如果有兴趣,可以看我之前的博客 C++:初始化、输入输出、const、引用、inline中关于const的这一部分,里面阐述了我的思想,也基本举出了全部例子
- 而另一个好处就是在C++中的强转const_cast中,去常性强转,去除的只是底层const,但我测了一下顶层const也可以去除举例:
const int a = 10;
int& b = const_cast<int&>(a);//true,合理合法的去除了a的顶层const
int b = 10;
int* const p = &b;
int* q = const_cast<int*>(p);//true,去除了p的底层const
二、顶层/底层const与auto、decltype的问题
结论:
- auto一般会忽略掉顶层const,
- 而decltype则顶层、底层const都能推断出来
举例:
const int a = 10;
const int* const p = &a; //p : const int* const
auto q = p; //q : const int *
int b = 20;
const int* const p = &b; //p : const int* const
decltype(p) q = &b; //q : const int * const
三、C++中,圆括号()、花括号{}对vector进行初始化的问题
在C++中,圆括号()代表的是构造的意思,花括号{}代表列表初始化的意思。
- 圆括号仅用于构造,不能用于单个初始化,必须要指定向量的大小
- 花括号也可以构造,也可以列表初始化,但要具体问题具体分析:若花括号的类型不符合元素类型,那么就要考虑用这样的值来构造vector对象了
举例:
vector<int> a1; //初始化状态为空
a1[0]; //false 没有元素
vector<int> a2 = 10; //false 必须用指定初始化形式指向向量的大小
vector<int> ar(10); //10个0
vector<int> v1{10}; //一个10
vector<int> br(10,42); //10个42
vector<int> v2{10,42}; //两个元素,10和42
vector<string> v3{10}; //10个""
vector<string> v4{10,"hi"}; //10个"hi"
vector<string> v5{"hello","world"}; //true
vector<string> v6("hi"); //false 圆括号不能用来单个初始化,必须指定向量初始化大小