了解C++默认提供和调用的函数

  • 编译器会自动为每一个空类创建构造函数、拷贝构造函数、赋值运算符以及析构函数

  • 不要使用编译器自动创建的函数,要杜绝这种情况发生,自己编写这些函数

如果不想使用编译器自动生成的函数,要明确拒绝

  • 编译器默认提供的函数,不仅不能给编程带来便利,而且会给在某种情况下引入难以定位的bug,因此应该明确拒绝

  • 拒绝的方式就是明确声明该函数为私有且不提供函数体

    • 私有表示对权限的控制,防止外部在意想不到的情况下调用

    • 不提供函数体,是让编译器在链接的时候报错,明确提示你注意这个函数

class Uncopyable{
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
}
//作为基类继承即可

为多态的基类声明virtual析构函数

  • 如果一个类中有一个虚函数,那么必须将析构函数也申明成虚函数,主要是防止资源泄露(使得析构从下向上依次执行)

  • 如果涉及的类不用于多态,那么就不要声明虚函数,因为虚函数的调用需要借助虚函数列表,调用的效率没有普通函数高

  • 如果不想一个类被实例化,那么就声明该类的虚函数为纯虚函数,且提供其实现

class AbstractClass
{
public:
virtual ~AbstractClass();
} AbstractClass::~AbstractClass()
{
//函数实现
//目的是进行资源释放
}

把异常消灭在析构函数中

  • 析构函数绝对不要吐出异常,这会导致资源部分释放的问题,析构函数中的异常一定要try...catch处理

  • 如果客户需要对某个操作做出反应,且有可能抛出异常,那么就需要提供一个普通函数执行该操作,这样设计的好处:

    • 提供普通函数给客户使用,且明确会抛出异常,使得用户有机会对异常做出合理的处理

    • 析构函数中检查资源释放的状态,做最后的处理

class DBConn
{
private:
DBConnect dbc;
bool closed;
public:
void close()
{
dbc.close();
closed = true;
} ~DBConn()
{
if(!closed)
{
try
{
dbc.close();
} catch(...) {
//停止或记录
}
}
}
}
//解决close会跑出异常的可能

绝不在构造函数和析构函数中调用virtual函数

  • 看清楚描述,是构造函数和析构函数中不能调用虚函数;析构函数本身是可以设计成虚函数的,且在某些情况下,必须设计成虚函数

  • 在构造函数未执行完成之前,类的虚函数表未建立

  • 进入析构函数之前,类的虚函数表已经销毁,无法调用

让operator=返回一个reference to *this

好处:便于连续赋值,类似下面这种执行方式:

a = b = c = d //连续赋值
class Widget
{
public:
Widget& operator+=(const Widget& rhs)
{
return *this;
}
}

在operator=中处理自我赋值

  • 确认任何函数操作一个以上的对象,且对象可能重复,那么需要进行自我赋值的校验

  • 进行自我赋值的判断:地址判断、copy-and-swap

  • copy-and-swap:交换两个对象的数据,在交换的过程中,任意一句语句发生异常,只会导致交换函数本身交换不成功,不会导致程序发生其他异常,程序依然可以运行,状态回到没有调用交换之前,唯一遗憾的就是程序的业务逻辑错了。这种函数我们叫异常安全函数

Widget& operator=(const Widget& rhs)
{
if(this == &rhs)
return *this;
// ...
return *this;
} Widget& operator=(const Widget& rhs)
{
Widget temp(rhs);
swap(temp);
return *this;
} Widget& operator=(Widget rhs) //拷贝发生在参数传入的过程中
{
swap(rhs);
return *this;
}

赋值对象时不要忘记其中的每一个成员

  • 代码静态检查时,有一条规则就是需要初始化每一个成员变量

  • 拷贝构造函数和赋值运算符不能相互调用---记住就好,如果有相同的代码可以提取成一个private函数

  • 拷贝构造的时候一定要拷贝自己的每一个成员,包括基类的每一个成员

高效C++:构造/析构/赋值的更多相关文章

  1. EffectiveC++ 第2章 构造/析构/赋值运算

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...

  2. 《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  3. 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  4. Effective C++ —— 构造/析构/赋值运算(二)

    条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...

  5. Effective C++笔记:构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...

  6. C++构造/析构/赋值函数

    在编写C++程序的时候,我们会为特定某一类对象申明类类型,几乎我们申明的每一个class都会有一个或多个构造函数.一个析构函数.一个赋值运算符重载=.以及拷贝构造函数.这些函数控制着类对象的基础操作, ...

  7. Effective C++ 笔记二 构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inlin ...

  8. Effective C++ -- 构造析构赋值运算

    05.了解C++默默编写并调用哪些函数 编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual 成员变量中有引用和const成员时,无法自己主动生成copy assign ...

  9. Effective C++笔记(二):构造/析构/赋值运算

    参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...

随机推荐

  1. JavaWeb网上图书商城完整项目--day02-12.激活功能各层实现

    1.我们来看程序的代码 数据库层: 1.通过激活码查找到对应的用户 2.设置用户的激活状态 2.业务层 1.通过数据库接口通过验证码得到对应的用户 2.判断当用户是否为空,如果没有通过激活码查找到对应 ...

  2. 慕课网 性能优化之MySQL优化--- max 和count的性能优化

    注:在执行SQL语句前加上explain可以查看MySQL的执行计划 数据库:MySQL官方提供的sakila数据库 Max优化: 例如:查询最后支付时间 explain select max(pay ...

  3. python0.1

    python基础 python是一种高级编程语言,而编程语言分为3种 编程语言 编程语言是一种人与计算机沟通的工具. 编程就是就将人的需求通过攥写编程语言命令计算机完成指令. 编程的意义在于将人类的生 ...

  4. 痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列ROM中的FlexSPI驱动API实现IAP. 痞子衡的技术交流群里经常有群友提问: i.MXRT中的FlexSPI驱动 ...

  5. js页面跳转的问题(跳转到父页面、最外层页面、本页面)

    "window.location.href"."location.href"是本页面跳转 "parent.location.href"是上一 ...

  6. JavaScript基础-即时函数(Immediate Functions)(017)

    1.即时函数的声明方法 即时函数(Immediate Functions)是一种特殊的JavaScript语法,可以使函数在定义后立即执行:(function () {    alert('watch ...

  7. AcWing 走廊泼水节 题解

    这道题大致题意就是让一棵树任意两点有连边(也就是完全图),但是补完后最小生成树是一开始的那棵树,问最小加的边权之和是多少. 了解题意后,我们可以想到用Kruskal(废话),当每两个集合合并的时候,除 ...

  8. 题解 P3870 【[TJOI2009]开关】/基础分块学习小结

    直接进入正题: 分块: 分块分块,就是把一个长串东西,分为许多块,这样,我们就可以在操作一个区间的时候,对于在区间里面完整的块,直接操作块,不完整的直接操作即可,因为不完整,再加上一个块本身就不大,复 ...

  9. 看源码,重新审视Spring Security中的角色(roles)是怎么回事

    在网上看见不少的博客.技术文章,发现大家对于Spring Security中的角色(roles)存在较大的误解,最大的误解就是没有搞清楚其中角色和权限的差别(好多人在学习Spring Security ...

  10. mysql 导入sql脚本中文乱码问题

    1.数据库是否utf8 2.sql文件是否utf8