条款3:尽可能使用const
const关键字:允许我们指定一个语义约束(不该被改动),编译器强制实施这个约束。
案例一: 修饰指针
第一种(const 在 * 的左边):
const char* cp = greeting; //或者char const * cp = greeting; 这个格式也行
表示指针指向的内容是常量,无法通过指针修改内容。但可任意改变指针指向
第二种(const 在 * 的右边):
char* const p = greeting;
表示指针是本身常量,无法任意改变指向,但对于指向的数据可以修改。
第三种( const 在 * 的左边和右边):
const char* const p = greeting
表示指针是常量并且指针指向的数据是常量
案例二: STL迭代器相关
说明:迭代器,本质类似于一个T* 的任意类型的指针。
问题:const vector::iterator 和 vector::const_iterator区别?
- const vector::iterator:相当于对指针赋予常量特性,无法任意改变指向,但可修改指向的数据。
std::vector<int>vec;
const vector<int>::iterator it = vec.begin();
it++ ; //这句是错误的
*it = 0; //可以写
int a = *it; //也可以读
- vector::const_iterator:后者相当于指针指向的数据是常量,可以改变指针指向,但是无法修改指向的数据
std::vector<const int>vec;
vector<int>::const_iterator it = vec.begin();
it++ ; //这句是正确的的
*it = 0; //这句是错误的,不可以写
int a = *it; //可以读
案例三: 修饰类的成员函数
举个小例子:
class Game()
{
public:
//void Play(string name); //去掉注释,就表明实现const重载
void Play(string name) const;
private:
string GameName;
}
void Game::Play(string name)
{
//这样的操作若是没有对应的非const函数,则一定无法通过编译
GameName = "xxxxx";
}
废话不多说,直接给出总结!
- const修饰类的成员函数表明该方法不对类成员做任何修改
- 扩大了操作的对象范围,既可以操作const对象也可操作非const对象
- 含有const修饰的成员函数和不含const的可以构成函数重载
提问:但若现在有需求又必须要在const修饰的成员方法中对类成员变量修改呢?
答:通过mutable关键字修饰需要被修改的成员变量
class Game()
{
public:
//void Play(string name); //去掉注释,就表明实现const重载
void Play(string name) const;
private:
mutable string GameName; //这样就表示该变量可以被const函数修改
}
void Game::Play(string name)
{
//这样的操作可以通过编译
GameName = "xxxxx";
}
案例四: 特殊场景下,避免代码大片重复
案例如下:
class TextBlock
{
public:
const char& operator[] (unsigned pos) const
{
.........................
return text[pos];
}
char& operator[] (unsigned pos)
{
.........................//代码和上述一样
return text[pos];
}
private:
string text;
}
如此重复性的代码,是不是对于洁癖的程序员来说有点难受?
所以我们有如下的一个取巧的方法。通过非const调用const避免代码重复!
解决方案如下:
class TextBlock
{
public:
const char& operator[] (unsigned pos) const
{
..............
xxxxxxxxxxxxxx
oooooooooooooo
return text[pos];
}
char& operator[] (unsigned pos)
{
//两次的类型转换实现
//第一次将自己转成const类,从而可以调用const函数
//第二次将调用后的const char&结果转成char&
return const_cast<char&>( static_cast<const TextBlock&> )(*this)[pos];
}
private:
string text;
}
综上,对于const的态度如下:
1、有条件尽可能声明为const,可以减少一些错误用法
2、const 对于指针和迭代器上概念容易混淆,多思考
3、对于const和非congst成员函数实质相同,可以避免代码重复
结尾: 我是航行的小土豆,喜欢我的程序猿朋友们,欢迎点赞+关注哦!希望大家多多支持我哦!有相关不懂问题,可以留言一起探讨哦!
如有引用或转载记得标注哦!