11.为须要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符。

显然,由于动态内存分配,绝对会有深浅拷贝的问题,要重写拷贝构造函数。使其为深拷贝,才干实现真正意义上的拷贝。这是我理解的关于要声明拷贝构造函数的原因。

而对于赋值操作符,类似的道理。

	A b = a;
b = a;

对于上述两种形式,上面调用的是复制构造函数,而以下才是 赋值操作符=。

赋值与复制非常类似,缺省的操作都是将类的所有成员进行复制。

深拷贝基本的操作非常easy,对于指针。动态申请一块内存来存放指针指向的数据,每一个指针都指向自己的一块内存,而不是其它人的。

12.尽量使用初始化而不要在构造函数里赋值。

即尽量使用成员初始化列表,而不是使用赋值的方法。

首先对于const成员和引用,仅仅能使用初始化列表来初始化。

其次初始化列表效率更高。由于对象的创建分为两步:数据成员的初始化和运行被调用构造函数体内的动作。即使用赋值之前。先进行了数据成员的初始化,然后才是赋值。所以使用初始化列表效率更高。

但当有大量的固定类型的数据成员要在每一个构造函数中以同样的方式初始化的时候,使用赋值会更加合理一点。

13。初始化列表中成员列出的顺序和它们在类中声明的顺序同样。

这是由于初始化列表的顺序并不影响初始化的顺序。初始化的顺序是有成员在类中声明的顺序决定的。而让其顺序同样是使程序看起来是依照初始化列表的顺序初始化。

而c++不使用初始化列表的顺序的原因是:对象的析构函数是依照 与成员在构造函数中创建的相反的顺序 创建的。

则假设对象不是依照一种固定的顺序来初始化,编译器就要记录下每一个对象成员的初始化顺序。这将带来较大的开销。

14、确定基类有虚析构函数。

通过基类的指针去删除派生类的对象时,基类一定要有虚析构函数,不然 会有不可预測的后果。不使用虚析构函数,仅仅调用基类的析构函数去删除派生类对象,这是无法做到。也是无法确定后果的。

构造函数调用是先基类后派生类,而析构函数的顺序是先派生类后基类。

当一个类不作为基类使用时,使用虚析构函数是一个坏主意。由于虚函数的对象会有一个虚指针指向虚表。会浪费空间来储存这个没有意义的指针。

纯虚函数在虚函数后加 =0 就可以。

15.让operator = 返回 *this 的引用。

= 号能够连接起来。由于其返回值的原因,声明operator=的形式例如以下:

C& C:: operator= (const C&);

其输入和返回都是类对象的引用。以实现连续的赋值操作。

返回值是 = 左边值的引用 即 *this的引用,由于右边即參数是const类型的。
函数的參数是 const类型的原因,是 = 右边的值经过计算会获得一个新的结果,而这个对象要用一个暂时对象来储存,这个暂时对象是const类型的,由于其作为函数的參数。且不能被函数改动。

16.在operator = 中对所有数据成员赋值。

对于深拷贝要自己写一个更加正确的 = 操作。

在涉及继承时。派生类的赋值运算必须处理基类的赋值。

假设重写派生类的赋值运算,就必须同一时候显示的对基类部分进行赋值。

class A{
public:
int a;
A(int x):a(x){}
// A& operator=(const A& x){ a = x.a; return *this;}
};
class B:public A{
public:
int b;
B(int x):A(x),b(x){}
B& operator=(const B&);
};
B& B::operator=(const B& x){
if(this == &x)return *this;
// A::operator=(x);//调用基类的赋值函数要如此写
static_cast<A&>(*this) = x;//也能够强制转换为A类型然后在调用基类的默认赋值函数
b = x.b;
return *this;
}

拷贝构造函数也是如此。也要对基类的成员进行复制,仅仅要在成员初始化列表中加入基类就可以。

17.在operator=中检查给自己赋值的情况。

这是基于效率考虑的,在赋值的首部检測是给自己赋值,就马上返回。如16中函数所写的那样。

这里除了类中自己成员的赋值。假设有基类,还要调用基类的赋值函数,会添加开销。

还有一个原因是保证正确性。一个赋值运算符必须首先释放掉一个对象的资源。如有些指针指向了动态申请的空间。则赋值前一般要释放这些资源,然后在指向新的资源(假设在赋值開始。用些暂时的指针来记录之前的所有指针指向的内存,然后在赋值后再将暂时指针指向的内存所有释放。这还是不行,由于对这些指针如p,必须有 p = new p[]...来指向新申请的一块空间,而假设是同一个对象的话,这里就将原来的指针指向一个新的地址,且两者同样了,所以又须要一个新的暂时指针来指向赋值对象的指针的值)。也就是说为了使其给自己赋值,对与每一个指针必须新建两个指针。一个储存左边的对象的原指针,一个储存右边的对象的原指针,这种开销时极大极浪费的,也是没有必要的,为了一些不应该进行的为自己赋值要提前准备大量内存来储存数据,这也是不科学的。

所以最好的解决的方法是检測是否为自己赋值,一般採用检測对象地址是否相等,c++中一般採取这个方案。对于java中。不好的做法是检測对象是否相等。即其所有值是否全然相等,较好的方法是依据对象的id来推断对象是否为同一个对象。

Effective C++ 11-17的更多相关文章

  1. International Programming Retreat Day(2018.11.17)

    时间:2018.11.17地点:北京国华投资大厦

  2. Notes of Daily Scrum Meeting(11.17)

    Notes of Daily Scrum Meeting(11.17) 今天是第四周的周一,也就是说距离最后发布也只剩下一周的时间,但我们的工程里面还有很多的问题没有解决,我关注过 其他一两个小组,他 ...

  3. Beta周第8次Scrum会议(11/17)【王者荣耀交流协会】

    一.小组信息 队名:王者荣耀交流协会 小组成员 队长:高远博 成员:王超,袁玥,任思佳,王磊,王玉玲,冉华 小组照片 今天拍照的人是王磊.因此他没有出现在照片中. 二.开会信息 时间:2017/11/ ...

  4. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

  5. C++98/11/17表达式类别

    目标 以下代码能否编译通过,能否按照期望运行?(点击展开) #include <utility> #include <type_traits> namespace cpp98 ...

  6. 2016/11/17 周四 <javascript的封装简单示例>

    这是一个简单的javascript代码封装的示例以及封装后的调用方法: var ticker={ n:0, add:function() { this.n++; }, show:function() ...

  7. Sprint1(第四天11.17)

    Sprint1第一阶段 1.类名:软件工程-第一阶段 2.时间:11.14-11.23 3.选题内容:web版-餐厅到店点餐系统 4.团队博客地址: http://www.cnblogs.com/qu ...

  8. 【Alpha版本】 第九天 11.17

    一.站立式会议照片: 二.项目燃尽图: 三.项目进展: 成 员 昨天完成任务 今天完成任务 明天要做任务 问题困难 心得体会 胡泽善 完成我要应聘的详情显示,解决头像不能显示的问题,完成了报名及取消操 ...

  9. Effective Java 11 Override clone judiciously

    Principles If you override the clone method in a nonfinal class, you should return an object obtaine ...

  10. Effective C++(11) 自我赋值(a=a)时会发生什么?

    问题聚焦: 自我赋值看似有点愚蠢的行为,其实总会发生的 首先:它是合法的, 其次,它不一定是安全的, 再次,它有时候不是那么明显. 先看一个Demo class Widget { ... }; Wid ...

随机推荐

  1. HDU 6125 Free from square (状压DP+分组背包)

    题目大意:让你在1~n中选择不多于k个数(n,k<=500),保证它们的乘积不能被平方数整除.求选择的方案数 因为质数的平方在500以内的只有8个,所以我们考虑状压 先找出在n以内所有平方数小于 ...

  2. [读书笔记] R语言实战 (十四) 主成分和因子分析

    主成分分析和探索性因子分析是用来探索和简化多变量复杂关系的常用方法,能解决信息过度复杂的多变量数据问题. 主成分分析PCA:一种数据降维技巧,将大量相关变量转化为一组很少的不相关变量,这些无关变量称为 ...

  3. 基于element的表单渲染器 (el-form-renderer)

    基于 element-ui 封装的表单渲染器,完整继承了 element 的属性定义,并进行了简单扩展,从而用户能够通过使用一段预设的数据渲染出一个完整的 element 表单. 演示地址 项目地址 ...

  4. 基于Quick_Thought Vectors的Sentence2Vec神经网络实现

    一.前言 1.Skip-Thought-Vector论文 https://github.com/ryankiros/skip-thoughts 2.本文假设读者已了解Skip-Gram-Vector和 ...

  5. Maven下Flex国际化配置

    之前写了flashbulid.initellij下的flex国际化配置,它们都是在本地打包发布的,那么我们的工程用maven管理了,需要自动发布.这时候如何修改flex的pom文件,来让它build的 ...

  6. Virtual Box 新建一个虚拟机安装系统(补充:WIN7 64 bit 系统虚拟机无法安装 64 bit 系统问题)

    1.安装Virtual Box好后,点击新建 2.配置内存大小,这个根据自己需要配置就好 3.创建虚拟硬盘 这里选择固定分配.动态分配都可以,接下来就分配硬盘大小了 4.新建好后我们点击刚才建立的虚拟 ...

  7. Vue基础知识点

    基础知识: vue的生命周期: beforeCreate/created.beforeMount/mounted.beforeUpdate/updated.beforeDestory/destorye ...

  8. java数组简单逻辑代码

    package cuteSnow; public class HelloWorld { // 遍历数组里面的每个数字 public static void print(int[] array){ St ...

  9. 数人云CTO解读Docker 1.12和金融业容器化

    7月29日 数人云 在上海举办金融沙龙,邀请上交所和近二十家来自银行.保险.证券的IT技术专家一同探讨容器技术在金融业中的最佳实践.数人云CTO肖德时在会上将传统金融行业通过容器可以解决的四大问题做了 ...

  10. HDU 3723

    把向上看成+1,向下看成-1.可以知道符合卡特兰数的一般解释了.记作Can(i) 中间平过的即是0.亦即是C(n,2*i),i表示向上的数. 于是总的就是sum(C(n,2*i)*Can(i)),i从 ...