Effective C++笔记(2)—使用const
2016-08-12 22:41
113 查看
1.尽可能使用const
const的用法一直让人头疼,加上指针或引用就更头疼了,以前特意学习过一次【C++const限定符】,可能那个时候还不够深刻,这次借看书再次学习一蛤。1.1const修饰指针的形式
先看书中的一个例子:char greeting[]="Hello"; char *p=greeting;//non-const pointer,non-const data const char* p = greeting;//non-const pointer,const data char *const p = greeting;//const pointer,non-const data const char * const p = greeting;//const pointer,const data
上面的注释会有些迷惑,在这之前,我们清楚的知道,const可以从两个层面去限定:指针本身和指针所指向的内容。因为指针本身只是一个栈上变量而已,他存放的所指对象的地址。
然后就是关于const对指针及其所指向对象的修饰了。
Bjarne在他的The C++ Programming Language里面给出过一个助记的方法:
把一个声明从右向左读( * 读成 pointer to )。
char * const cp; //cp is a const pointer to char //即常量指针(指针本身const) const char * p; //p is a pointer to const char; //指向常量的指针(指针所指向的对象const)
在EffectiveC++中,则给出这样一个论断:
如果关键字const出现在星号的左边,则被指物为常量;
如果出现在星号右边,表示自身是常量;
如果出现在星号两边,表示被指物和指针都是常量。
也因为这个论断,我们就清楚了其实下面两条语句其实是同一个东西:
const Widget *pw; Widget const *pw; //都是指向常量的指针
1.2char指针和char数组的区别
现在就清楚多了,不过还需要清楚一个区别:char * greeting="Hello"; char greeting[]="Hello";
首先,“Hello”字符串是存放在字符常量区,在内存中是只读的。
char * greeting="Hello";表示栈中变量
greeting存放字符常量区“Hello”的地址,但是由于“Hello”是只读的,于是
*greeting='s';这样的语句虽然没有error,但是运行时是有问题的。
而对于
char greeting[]="Hello";来说,会拷贝一份“Hello”到栈中,因此
*greeting='s';去修改其值是没有问题的。参见:StackOverFlow的回答。
这也就解释了
char * greeting="Hello";没有const限定符修饰,我们可以去修改其对象,但这种修改行为是非法的会带来不可预见的错误。
1.3const迭代器
在STL源码剖析中对迭代器的解释很详细,STL迭代器根据指针的特性塑模出来,其作用就像一个T*指针,而将迭代器加上const限定符,就类似声明一个T * const一样(即常量指针),而当我们需要一个不可修改对象内容的迭代器时,使用
const_iterator,如下:
vector<int> vec; const vector<int>::iterator it=vec.begin(); *it=10;//ok,改变所指对象内容 ++it;//error,类似常量指针 /*******************************/ vector<int>::const_iterator cit=vec.begin(); *cit=10;//error,不能改变所指内容 cit++;//ok,改变所指对象。
1.4const成员函数
在const成员函数中仔细学习过一波,对书中所说内容就不觉得陌生。许多人漠视一个事实:两个成员函数如果只有常量性(constness)不同,可以被重载。
这里就不再赘述其原理,记住成员函数的默认this参数即可,在
EffectiveC++书中也说,用操作符重载的方式举例也太过造作,举一个简单的例子:
class Test { private: int a; public: Test(int x) :a(x){} void print() const{ cout << "const called" << endl; cout << "a=" << a << endl; } void print(){ cout << "non const called" << endl; cout << "a=" << a << endl; } }; int main(int argc, char**argv) { Test t(2); const Test ct(1); t.print();//non-const called ct.print();//const called system("pause"); return 0; }
1.5mutable关键字
这里书中提到的两个流派:physical constness和
logical constness与成员函数修改成员变量的“力度”有关,前者认为,当成员函数只有在不更改对象的任何成员变量时才可以说成const,而成员变量中确实有一些变量需要修改怎么办,即使在const成员函数内?此时就需要用到
mutable关键字。某些成员变量是需要有mutable特性的,比如在muduo源码中,需要在一些const成员函数中使用Mutex加锁:参见muduo 06 互斥锁和条件变量的封装
1.6casting转型
过段时间会专门花一点时间了解一蛤const_cast、
static_cast和
dynamic_cast这几兄弟,这里简单的理解就是:
const_cast去掉const限定;
static_cast类型转换
说到转型跟const的联系,也就是作者认为,如果一个成员函数既有const的版本又有non-const版本,那么两份代码重复冗余了,因为他们干得活都是一样,为了使用const版本的成员函数来写non-const版本的成员函数,用到上述两种转型:
class TextBlock { public: const char & operator[](size_t position ) const { //.. //.. //.. return text[position]; } char & operator[](size_t position ) { //static_cast为*this加上const //const_cast为op[]的返回值移除const return const_cast<char&>( static_cast<const TextBlock&>(*this) [position] ); } };
相关文章推荐
- Effective c++笔记:03 尽可能使用const
- effective C++笔记之条款20、21:避免public接口出现数据成员、尽可能使用const
- Effective C++笔记之三:尽可能使用const
- effective c++条款21: 尽可能使用const
- Effective C++学习笔记——条款03:尽可能使用const
- 读书笔记_Effective_C++_条款三:尽可能使用const
- C++学习笔记8,const在函数方面的使用(二)
- C++学习笔记7,const关键字的使用(一)。
- More Effective C++ 阅读笔记(四)-- 避免使用隐式类型转换
- 【c++笔记七】教你使用"const类型的对象、成员函数"和"static类型的成员函数、变量"
- C++学习笔记(二):使用const、static类成员的注意事项
- Effective C++笔记之一:const 、enum、inline 代替#define的小结
- Effective C++_笔记_条款03_尽可能使用const
- Effective c++ 学习笔记——条款04:确定对象被使用前已先被初始化
- effective C++笔记之条款12: 尽量使用初始化而不要在构造函数里赋值
- more effective c++笔记1-----Item M2:尽 量使用C++风格的类型转换
- Effective C++学习笔记——条款03:尽可能使用const
- Effective C++笔记之三确定对象在使用前已初始化
- effective C++笔记之条款33: 明智地使用内联
- (笔记)关于函数形参中使用const引用和非const引用间的区别