Chapter 6
const与参数传递
回顾:顶层const与底层const
指针本身是一个对象,它可以指向一个对象。
-
顶层const表示(指针)本身是个常量。
-
底层const表示(指针)所指对象是个常量。
int i = 0;
int *const p1 = &i; // 顶层const,因为指针本身不能改变
const int ci = 42; // 顶层const,因为ci变量本身不能改变
const int *p2 = &ci;// 底层const,因为指针p2本身可以改变
const int *const p3 = p2; // 左——底层const,右——顶层const
const int &r = ci; // 声明引用:都是底层const
拷贝顶层const对象时,会忽略顶层const性质
const int ci = 42; // 如上,这是一个顶层const
int i = ci; // 拷贝ci,会忽略了它的顶层const属性
不能给p赋值,但可以通过p改变对象的内容
int * const p = &i; // 如上,这是一个顶层const
*p = 0; // 不能给p赋值,但可以通过p改变对象的内容
所以,参数传递时,也会发生类似上方的操作——形参的顶层const会被忽略掉
所以形参有顶层const的时候,可以传常量对象const int,也可以传非常量对象int
void fcn(const int i){/*fcn能读取i,但不能向i写值*/}
但如果定义了两次会产生错误
void fcn(const int i){/*fcn能读取i,但不能向i写值*/}
void fcn(int i){} // 实际上,和上一行是一样的,重复定义
回顾:变量初始化
int i = 42;
const int *cp = &i; // 底层const,不能通过cp改变i
const int &r = i; // 底层const,声明引用都是底层const,r不能改变i
const int &r2 = 42; // 底层const,声明引用都是底层const
int *p = cp; // 错误,p和cp类型不匹配,一个是const指针,一个不是
int &r3 = r; // 错误,r3和r类型不匹配,一个是const引用,一个不是
int &r4 = r2; // 错误,不能用字面值初始化一个非常量引用,引用不能绑定常量和表达式
应用到参数传递
int i = 0;
const int ci = i;
string::size_type ctr = 0;
reset(&i); // 调用形参是int*的
reset(&ci); // 错误,用const int对象初始化int*
reset(i); // 调用形参是int&的
reset(ci); // 错误,把普通引用绑定到const对象上ci
reset(42); // 错误,把普通引用绑定到字面值上
reset(ctr); // 错误,类型不匹配
find_char("Hello World!", 'o', ctr); // 第一个参数,用字面值初始化常量的引用
void reset(int &i){
i = 0;
}
void reset(int *ip){
*ip = 0;
ip = 0;
}
string::size_type find_char(const string &s, char c, string::size_type &occurs){
// ……
}