1.const定义变量时初始化流程。
分为运行时初始化和编译时初始化两种。
const int i = get_size(); //运行时初始化
const int j = 43; //编译时初始化
2.为什么在默认情况下,const对象仅在本文件内有效?
当以编译时初始化的方式定义一个const对象时,如下
const int j = 43; //编译时初始化,把代码中用到j的地方换成43
编译器将在编译过程中把用
到该变量的地方都替换成对应的值,如果程序包含多个文件,则每个用了const 对象的文件都应可以访问到他的初始值。为了支持这个用法,
同时避免对同一变量的重复定义,默认情况下,const对象仅设定为仅在文件内有效。
为了让const对象在多个文件均可共享,解决办法是,对于const 变量不管是声明还是定义都添加extern关键字。
//file_1.c定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufSize = fnc(); //运行时初始化
//file_1.h头文件
extern const int bufSize; //与bufSize是一个常量
3.常量与指针
int a = 0;
const int *p = a; //指向常量的指针
int* const p = &a; //常量指针
4.常量与引用
int i = 43;
const int &r1 = i; //正确,
const int &r2 = 42; //正确,相当于产生了一个临时量将r2绑定到临时对象上,const int tmp = 42;const int &r2 = tmp;
const int &r2 = r1 * 2; //正确,同上
//注意:没有 int& const r2 = i;
5. 常量与重载
带常量参数的重载需要区分底层const和顶层const
//合法的,区别是他们的引用类型的形参是否引用了常量,属于底层const
int calc(char, char);
int calc(const char&, char const&);
//合法的,区别是他们的指针类型的形参是否指向了常量,属于底层const
int calc(char, char);
int calc(char const*, char const*);
//非法的重载:两个函数的区别是他们形参本身(指针类型)是否为常量
//属于顶层const,属于精确匹配范畴:向实参添加顶层const或者从实参中删除顶层const
int calc(char a, char b);
int calc(char* const, char* const);
6.const与类
1.定义隐式形参this定为常量
//默认情况下this为指向非常量版本的常量指针,若需要兼容常量版本,需要在函数声明后加入const
class Sales_data {
public:
std::string isbn() const { return bookNo; }
private:
std::string bookNo;
};
2.底层const在类中的重载
//基于const this的成员函数重载
class Screen {
public:
Screen& display(std::ostream &);
const Screen& display(std::ostream &)const; //*this将返回常量引用
};
7.去除const属性
1.方法一:可以通过关键字mutable可变成员参数去const 类中的成员变量的常量属性
class People{
public:
//即使const对象也能被修改
int incAge()const
{ int last = age++; return last;}
private:
mutable int age = 1;
};
2.方法二:通过const_cast强制消除const属性,一般用在
函数重载中
const string &shorterString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
string &shorterString(string &s1, string &s2)
{
//返回类型为const string&,
auto &r = shorterString(const_cast<const string&>(s1), const_cast<const string&>(s2));
return const_cast<string&>(r); //r引用实际是绑定在非常量上,因此const_cast<string&>转化有效
}
int main(int argc, char** argv) {
string s("hello");
string l("hello world");
shorterString(s, l) += "!!!";
cout << "s = " << s << endl;
cout << "l = " << l << endl;
return 0;
}
//输出结果
s = hello!!!
l = hello world
附:关于const_cast使用注意事项
//const_cast使用注意:
1.本身为常量但转化为非常量为未定义行为
const int a = 1;
int *pa = const_cast<int*>(&a); //未定义行为
int& b = const_cast<int&>(a); //未定义行为
++b; //对a无效
cout<< a << b << endl; //调试打印为1 2
++(*pa);
cout<< a << (*pa)<<endl; //调试打印为1 3
2.只能转换底层const属性:
const int a = 1;
int b = const_cast<int>(a); //错误:const_cast只能改变底层const