关键字 auto

1
2
3
4
5
// OK
for (auto itor = _functionCode.cbegin(); itor != _functionCode.cend(); ++itor)
// ERR
for (auto const itor = _functionCode.cbegin(); itor != _functionCode.cend(); ++itor)
// why?

auto 能够自动推导常量吗?引用呢?——不能!

auto 一般会忽略掉顶层 const,如果希望推导出的 auto 类型是一个顶层 const,需要明确指出。P66

可以将引用的类型设为 auto,此时原来的初始化规则仍然使用。设置一个类型为 auto 的引用时,初始值中的顶层常量属性仍然保留。P66

const_iterator 可以读取元素,但不能修改元素的迭代器类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int main()
{
list<int> ages = { 1,2,3,4,5,6,7,8 };
{
// 不以 c 开头的函数都是被重载过的
list<int>::const_iterator cit = ages.begin();
list<int>::iterator it = ages.begin();
{
const auto cages = ages;
// 对一个 const 容器调用时,返回容器的 const_iterator 类型
cit = cages.begin();
// 可以将一个普通的 iterator 转换为对应的 const_iterator,但反之不行
//it = cages.begin(); // ERR
}
//*cit = 9; // ERR
*it = 9;
++cit;
cout << *cit << endl;
++it;
cout << *it << endl;
}
{
auto it = ages.begin();
++it;
const auto cit = ages.begin();
//++cit; //ERR
}
{
// 以 c 开头的版本是 C++ 新标准引入的,用以支持 auto 与 begin 和 end 函数结合使用
auto cit = ages.cbegin();
++cit;
cout << *cit << endl;
{
// 是 iterator 还是 const_iterator 依赖于容器的类型
auto it1 = ages.begin(); // list<int>::iterator
const auto cages = ages;
auto it2 = cages.begin(); // list<int>::const_iterator
// 但以 c 开头的版本还是可以获得 const_iterator 的,而不管容器的类型是什么
}
}
return 0;
}

注意区分 list<int>::const_iteratorconst list<int>::iterator,其实绕一圈还是 char const *char * const 的区别:前者 const 修饰指针指向的内容,指针可更改;后者 const 修饰指针本身,指针不可更改,但可更改其指向的内容。

1
2
3
4
5
6
7
8
9
10
11
char * ptr = "liyw";
{
char const * str = "niel";
str = ptr;
//str[1] = 'a'; // ERR
}
{
char * const str = "niel";
//str = ptr; // ERR
str[1] = 'a';
}

复合类型指针、引用等

用来修饰上层(最顶层)指针的 const ,称为顶层 const,表示指针是个常量;
相对应的,底层 const 用来表示指针所指的对象是一个常量。