//---------------------------15/03/26----------------------------

//#5    了解c++默默编写并调用哪些函数

{

/*

c++会默默帮你声明一个copy构造函数,一个copy assignment操作符重载,

一个析构函数,一个default构造函数。并且都是 public inline的

因此如果写下:

*/

class Empty{};

//就好像写下这样的代码:

class Empty

{

public:

Empty(){...}

Empty(const Empty& rhs) {...}

~Empty(){...}

Empty&operator=(const Empty& rhs){...}

};

//1:这些函数,只有被需求(被调用)时,才会被编译器创建出来

/**

2:copy构造函数和copy assignment操作符,编译器创建的版本只是单纯地

将来源对象的每一个non_static成员拷贝到目标对象中去

**/

//3:在copy的时候:如果成员变量有copy构造函数,编译器就调用其copy构造函数,

//如果没有copy构造函数,就会拷贝每一个bits
来完成初始化

/*

4:在什么情况下编译器拒绝帮忙定义一个copy assignment?

1>对象内包含一个reference变量,原因:reference自身不可以被再次指向另一个值

如果你想让这个reference的内容改变成目标对象的内容,那需要自行实现operator=操作

其实也就是深拷贝。

2>对象内包含一个const变量,原因:更改const变量的值时不合法的。

3>如果base classes将copy assignment操作符声明为private。原因:原本derived
classes

的copy assignment操作符是可以处理base class成分的,但是现在他们无法调用了。

编译器就两手一摊,无能为力了。

*/

}

//#6    若不想使用编译器自动生成的函数,就该明确拒绝

{

/*

当你想使你的对象不能被复制时(比如每个人的资产都是私有的,不该被复制给别人),

你有两个方法可以做到:                                                 */

//  1>自己声明一个private的copy构造函数以及copy assignment操作符。

class HomeForSale

{

public:

...

private:

...

HomeForSale(const HomeForSale&);

HomeForSale&operator=(const HomeForSale&);

};

// 这样就声明了这两个函数,要注意的是,不要去实现它,这样可以在别人

// 使用这两个函数时报错(编译器报错),当成员函数或friend函数使用时,会产生连接时报错

//  2>为了时报错提早(所有报错都由编译器产生),可以专门设计一个base类:

class Uncopyable

{

protected:

Uncopyable(){}

~Uncopyable(){}

private:

Uncopyable(const Uncopyable&);

Uncopyable&operator=(const Uncopyable&);

};

/*

这样只要想阻止copying行为,只需要继承Uncopyable类就可以了

这里会产生几个微妙的实现和运用

1>不一定需要使用public继承

2>Uncopyable的析构函数可以不是virtual的(这个类不是接口,只能算是一个属性)

3>Uncopyable中不含数据,符合一个empty base class optimization的资格

4>由于常常被继承,很可能造成多重继承。

*/

//总结:如果你的类常需要从多个基类继承,那最好自己声明两个copy函数,否则,不妨从

//Uncopyable那继承。

}

//#7    为多态基类声明virtual析构函数

{

/*

这一点,不必多说,只要了解c++多态,都知道要给多态基类声明一个virtual析构函数防治内存泄漏

这个条款中比较新鲜的东西有两个:

1:不要为一个非多态用途的类声明virtual析构函数。原因是:

1>这么做会使的对象占用内存变大,

尤其是对于一些小巧的类来说,本来可以直接放在一个寄存器中的,一声明vitual属性,

在32位系统中就变大了32bits,在64位系统中就变大了64bits。这个大小就是一个指针的大小,

这个指针就是vptr指针,指向虚函数表,里面存放着由函数指针
构成的数组。

2>由于vptr指针,这个对象将变得没有移植性。因为其他语言没有vptr这东西。

2:如果想使一个base class获得不能被实例化
的特性,而这个base calss中又没有

pure vitual函数(纯虚函数),可以把析构函数设置为pure vitual函数。值得注意的是

你还是要为这个析构函数提供一份定义。因为基类析构函数总是会在其派生类调用时被调用。

*/

}

//#8    别让异常逃离析构函数

{

// 如果析构函数可以吐出异常,会造成程序的结束执行或不明确行为,看下面的例子:

class Widget

{

public:

...

~Widget(){...}

};

void doSomething()

{

std::vector<Widget> v;

}

/*

当vector被销毁时,vector会依次调用其中的所有widget对象(假设有10个),如果析构允许

抛出异常的话,析构第一个的时候,抛出了异常,为了确保不会发生内存泄漏,必须继续析构其他

九个widget,如果第二个异常又被抛出,现在有两个同时作用的异常,在两个异常同时存在的情况下,

程序不是结束执行就是导致不明确行为。

*/

//如果析构函数必须执行一个动作,而该动作可能在失败时抛出异常,那么应该这么做

//给客户提供一个动作,让他自己去调用,并在析构函数中检查是否完成,并吞下异常或终止程序

class DBConn

{

public:

...

void close()

{

db.close();

closed =true;

}

~DBConn()

{

if(!closed)

{

try

{

db.close();

}catch (...)

{

//记下对close调用失败的log

//选择是否中止

}

}

}

private:

DBConnection db;

bool closed;

};

//这样可以给客户一个调用close的机会,如果他自己不处理,也没法抱怨设计这个类的我们了。

}

effective c++ 笔记 (5-8)的更多相关文章

  1. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  2. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  3. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  4. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  5. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  6. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  7. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  8. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

  9. Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记

    Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...

  10. effective c++ 笔记 (1-3)

    // //  effective c++.cpp //  笔记 // //  Created by fam on 15/3/23. // // //-------------------------- ...

随机推荐

  1. Qt与PyQT中设置ToolBar在AllowedArea的显示

    因为个人对传统的软件GUI界面不是太喜欢,最近又在学习Qt和PyQt5,所以就有了设置ToolBar在窗口的不同地方的想法,经过浪里淘沙,最终在Qt官网里找到了,原来再添加toolBar的时候是由设置 ...

  2. Linux命令网络命令之netstat

    Linux命令网络命令之netstat 这一年感觉到技术上成长到了一个瓶颈.可能是感觉自己学的东西足够应付目前的工作了,因此精神上就产生了懈怠,不思进取.到了一个技术氛围不错的公司,有许多专业能力很不 ...

  3. pt-heartbeat工具监控MySQL复制延迟

    pt-heartbeat工作原理: 1,在主库上的某个数据库A中创建一张heartbeat表,按照一定的时间频率更新该表的字段(把时间更新进去). 2,从主库连接到从上的这个数据库A中检查复制的时间记 ...

  4. beta冲刺————第三天(3/5)

    完善的具体内容: 前端: (1)可以进行修改文字大小背景 其中,金色的文字个人觉得很好看,点赞.(我很满意啊) (2)可以改变成夜间模式(也很不错啊) 后端: 尝试将本地的后端war文件,以及数据库传 ...

  5. 团队作业7——第二次项目冲刺(Beta版本)day1

    项目成员:  曾海明(组长):201421122036 于波(组员):201421122058 蓝朝浩(组员):201421122048 王珏 (组员):201421122057 叶赐红(组员):20 ...

  6. BZOJ5092:[Lydsy1711月赛]分割序列(贪心,高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b_2 xor...xor b ...

  7. PHP缓存锁原理及利用

    原文链接:https://blog.csdn.net/tim_phper/article/details/54949404 概述: 项目当中经常要考虑数据高并发的情况,为了避免并发导致出现一些资源重复 ...

  8. 补码与C++的应用

    12.inti=(int)((unsigned int)0xffffffff+(unsigned int)0xffffffff); printf(“%d”,i);结果是:C A.0           ...

  9. 列表操作方法,元祖,for循环嵌套

    li = ['alex','wusir''女神']增 1.增加到列表末位 li.append() 连续增加,输入q停止 li = ['alex','wusir''女神'] while 1: s = i ...

  10. VC++ MFC单文档应用程序SDI下调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错原因分析及解决办法:glewInit()初始化的错误

    1.问题症状 在VC++环境下,利用MFC单文档应用程序SDI下开发OpenGL程序,当调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错,出错代码如下: OpenG ...