Effective C++ iterm3

条款三

--17/1/16

这个条款主要是介绍了const在c++的各个应用,看完之后真的是受益匪浅。

(1)首先const的修饰可以确保指针或者指向的东西是不是const,和我们在条款二看到的常量指针和指针常量类似,一下是具体定义:

T * const:const pointer,non-const data 也就是我们所说的指针常量;

const T *:non-const pointer,const data 也就是我们所说的常量指针;

值得注意的一点是写在类型前和类型后是一样的,也就是const T* p和T const*p是一样的,都是常量指针,T是不变的对象。

在STL里面的指针也有类似的形式:

a.为迭代器声明指针,指的是T*const,也就是不允许改变指针指向的地址,写法如下:

const std::map<int,int>::iterator it = mp.begin();

b.希望仅是迭代来遍历想要的内容,不允许修改具体容器里面的值,也就是const T*这时候需要的是STL提供const_iterator,写法如下:

std::map<int,int>::const_iterator it = mp.begin();

以上就是const在指针和迭代器的一个重要的应用。

(2)const在函数声明的应用也是应用广泛并且要提高注意的地方。令函数返回一个常量值可以提高安全性和高效性。比如这样的句子是会通过编译的:

 1 class R {
 2 public:
 3   R() {}
 4 };
 5
 6 R operator * (const R& l, const R& r) {
 7   R t;
 8   return t;
 9 }
10
11 int main() {
12   R a, b, c;
13   (a * b) = c;
14   return 0;
15 }

虽然这样写脑洞大了点,但是这是一个不可被忽视的问题,将函数声明为const能够增加安全性同时也可以被编译器捕捉这样的“无聊之举”?

(3)const成员函数中的应用是本条款花费大篇来通说的内容,我们希望这个成员函数不可修改类的相关值,我们会为这个函数加上const的字样。可以依据const与否来进行重载,const成员调用const函数,non-const调用non-const版,这个在Essential c++也提到过相关知识。

这时候作者就讨论两个派别的const成员函数:

1)bitwise constness,要求每一位的是constness,也就是const函数里面不允许有任何的修改操作,所以编译器着重检查的是类似赋值的操作。

下面这段代码却不是真正意义上的bitwise constness

 1 class R {
 2
 3 public:
 4
 5   R(const char *p) {
 6
 7     str = new char[strlen(p) + 1];
 8
 9     strcpy(str, p);
10
11  }
12
13  char& operator [] (int _index) const {
14
15   return str[_index];
16
17  }
18
19  void print() const {
20
21   printf("%s\n", str);
22
23  }
24
25 private:
26
27   char *str;
28
29 };
30
31
32
33 int main() {
34
35   R r("zhenhao");
36
37   r.print();//输出 zhenhao
38
39   char *p = &r[0];
40
41   *p = ‘h‘;
42
43   r.print();//输出 hhenhao
44
45   return 0;
46
47 }

2)因此第二种就是logical constness一个const成员函数是可以修改里面的相关变量的,也就是逻辑上是“不可变的”就好了。这个问题在Essential C++里面就特别讨论过,使用mutable关键字将你想要放在const成员函数里面的变量可以变,而不是所有变量都不能变。

最后作者做了一个总结我觉得不错:编译器严格实行bitwise constness,但是写程序是应该遵守的是logical constness。

(4)巧妙使用转换避免const和non-const的重复,当我们实现两种版本的函数时,如果实现机制没有什么区别,那么可以利用转换来避免这个重复。这个避免的实现在non-const的成员函数内,将non-const成员转换成const(安全的),然后调用相应的const函数之后返回的值利用const_cast来进行转换回来即可。注意强调的是不可以将const转换成non-const,因为这不仅在逻辑上不成立,而且实现起来也麻烦。

时间: 2024-11-05 13:25:54

Effective C++ iterm3的相关文章

《Effective C++》读书笔记汇总

我之前边读<Effective C++>边写下每个条款的读书笔记,这一版是C++11之前的版本.这里我将每个条款令我印象深刻的点小结一下. 1.C++包括:Plain C(面向过程).OOP(面向对象).模板(泛型和模板元编程).STL(C++标准库). 2.用inline.enum.const代替#define.#define定义的宏,一旦复杂起来,高手都很难掌控.不要带入C的习惯. 3.灵活使用const前缀.不需要进行改变的数据加上const前缀.指针的const前缀有两种形式,cons

Effective Java之内部类

Effective Java中对类的权限,接口等的要求,总结起来就是够用就行,不要赋予过多的访问权限,类的定义也是,如果某个类只会在类的内部使用,那就将该类定义为内部类吧. 内部类分为四种: 1.静态内部类:静态内部类就是在class前面多了static关键词的内部类,这种类和类的静态方法和静态变量一样,针对类本省进行操作,在静态内部类中可以随意访问其所在类的静态方法和静态变量. 2.非静态内部类:和静态内部类相对于,其实在类内部定义的所有东西只是受到访问修饰符的限制,所以非静态内部类和类的非静

学习日记之状态模式和Effective C++

状态模式(State):当一个对象内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类. (1),状态模式主要负责解决的是当控制一个对象转换的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化. (2),状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来. (3),将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和

Effective Objective-C 2.0重读笔记---1

上次看这本书的时候匆匆走了一遍,最近不太忙,重温了一遍,把笔记写出来~.. 有兴趣的可以去买一本,感觉这本书还是挺不错的 由于大部分是在坐车的时候用手机写的,所以代码很少,图也很少 1. 尽量使用向前声明,延后引入头文件的时间,这样可以减少编译时间2. 使用arraywithobjects:....如果遇到为空的变量,就会自动终止,后面的变量便会添加不上,切不会报错,会造成数据不一致问题,所以尽量使用字面量语法创建相关对象,减少出错且减少代码量3. 使用字面量创建的对象都是不可变的,如果要获得可

Effective前端2:优化html标签

  借用Effective之名,开始写Effective系列,总结一些前端的心得. 有些人写页面会走向一个极端,几乎页面所有的标签都用div,究其原因,用div有很多好处,一个是div没有默认样式,不会有margin.background等初始化设置,另外可能会觉得不用div还能用啥.所以看他的页面,一展开是div,再展开还是div,展开四.五层都是div. 这样对用户来说虽然没什么区别,但是作为一名有追求的程序员,这种写法看起来是比较难受的.有些人虽然知道html5新增了很多标签,但也不怎么去

Effective前端1:能使用html/css解决的问题就不要使用JS

  借用Effective之名,开始写Effective系列,总结一些前端的心得. 为什么说能使用html/css解决的问题就不要使用JS呢?两个字,因为简单.简单就意味着更快的开发速度,更小的维护成本,同时往往具有更好的体验,下面介绍几个实例. 1. 导航高亮 导航高亮是一种很常见的问题,包括当前页面的导航在菜单里面高亮和hover时高亮.你可以用js控制,但是用一点CSS技巧就可以达到这个目的,不需要使用JS. 在正常态时,每个导航的默认样式为: 正常态透明度为0.5 CSS 1 2 3 n

【总结】Effective java经验之谈,类与接口

转载请注明出处:http://blog.csdn.NET/supera_li/article/details/44940563 Effective Java系列 1.Effective java经验之谈,创建和销毁对象 2.Effective java经验之谈,泛型 3.Effective java经验之谈,类与接口 4.Effective java经验之谈,通用方法 5.Effective java经验之谈,枚举,注解,方法,通用设计,异常 6.Effective java经验之谈,并发编程

阅读《effective java-第17条》遇到的问题解决与分享

问题背景 最近这2天准备重新看一遍<effective java>,发现这些经典的书籍真的是看一遍又有一遍的感受.也越来越觉的学习的过程是一个重复的过程.这次遇到的问题是在第17条中看到的,看了蛮久都没有看懂视例代码.第17条的内容是要么为继承而设计,并提供文档说明,要么就禁止继承.在其中有一段示例构造器决不能调用可被覆盖的方法代码如下: 父类代码 package com.sitech.test; /** * effect of java * @author liaowp * */ publi

《Effective C++》之条款34:区分接口继承和实现继承

<Effective C++> 条款34:区分接口继承和实现继承 Public继承由两部分组成 函数接口继承 函数实现继承 三种可能面对的继承 derived class 只继承成员函数的接口 derived class 同时继承函数的接口和实现,但又希望能够覆写它们所继承的实现 derived class 同时继承函数的接口和实现,但不允许覆写任何东西 总结: 接口继承和实现继承不同.在public继承下,derived classes 总是继承base class 的接口. Pure vi