高效C++:构造/析构/赋值
了解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++:构造/析构/赋值的更多相关文章
- EffectiveC++ 第2章 构造/析构/赋值运算
我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...
- 《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- Effective C++ —— 构造/析构/赋值运算(二)
条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...
- Effective C++笔记:构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...
- C++构造/析构/赋值函数
在编写C++程序的时候,我们会为特定某一类对象申明类类型,几乎我们申明的每一个class都会有一个或多个构造函数.一个析构函数.一个赋值运算符重载=.以及拷贝构造函数.这些函数控制着类对象的基础操作, ...
- Effective C++ 笔记二 构造/析构/赋值运算
条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inlin ...
- Effective C++ -- 构造析构赋值运算
05.了解C++默默编写并调用哪些函数 编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual 成员变量中有引用和const成员时,无法自己主动生成copy assign ...
- Effective C++笔记(二):构造/析构/赋值运算
参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...
随机推荐
- opencv C++构造并访问单通道和多通道Mat。
一:构造并访问单通道. int main(){ cv::Mat m=(cv::Mat_<int>(3,2)<<1,2,3,4,5,6); for(int i=0;i<m. ...
- Git执行"git rebase -i HEAD~xxx"报错:git rebase fatal: Needed a single revision invalid upstream –i
一.问题"git rebase -i HEAD~xxx"是修改git 历史记录的一个很有用的命令. 但是有时在执行该命令时会出现以下错误:$ git rebase –i HEAD~ ...
- jni不通过线程c回调java的函数 --总结
1.JNIEnv类型是一个指向全部JNI方法的指针.该指针只在创建它的线程有效,不能跨线程传递 2.JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的. ...
- vue与react对比总结(一)
一.react和vue设计上的共同理念 1.使用 Virtual DOM 2.提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件. 3.将注意力集中保持在核心库,而将其 ...
- springboot + rabbitmq 用了消息确认机制,感觉掉坑里了
本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...
- 告别传统机房:3D 机房数据可视化实现智能化与VR技术的新碰撞
前言 随着各行业对计算机依赖性的日益提高,计算机信息系统的发展使得作为其网络设备.主机服务器.数据存储设备.网络安全设备等核心设备存放地的计算机机房日益显现出它的重要地位,而机房的环境和动力设备如供配 ...
- 错误记录-MySql.Data.MySqlClient.MySqlException (0x80004005): Timeout expired.
-- ::25.026 +: [ERR] Connection id "0HLQH64H76UL5", Request id "0HLQH64H76UL5:0000000 ...
- C#客户端通过安全凭证调用webservice
怎么解决给XML Web services 客户端加上安全凭据,从而实现调用安全的远程web方法?首先,有远程web服务Service继承自System.Web.Services.Protocols. ...
- 阿里云安全组规则授权对象设置为固定IP段访问
阿里云的ESC建站需要在安全组放通一些端口才能正常访问,所以我们在开放端口的时候就直接设置了全部ip可访问,授权对象填入0.0.0.0/0,意味着允许全部ip访问或者禁止全部ip访问. 但是我们有了一 ...
- 「疫期集训day12」阴雨
我们走进了泥泞的雨林----阿尔贡森林里艰难前进的士兵 今天考试一般,T1T2签到题没啥好说的,剩下三个小时全肛T3(我脑子有泡,前几天刚做了一道类似T4的难题,公式更难推),9:00->10: ...