Effective C++条款05:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls)
Effective C++条款05:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls)
- 条款05:了解C++默默编写并调用哪些函数
- 编译器为类生成的默认函数做了什么?
- 总结
《Effective C++》是一本轻薄短小的高密度的“专家经验积累”。本系列就是对Effective C++进行通读:
条款05:了解C++默默编写并调用哪些函数
什么时候 empty class(空类)不再是个空类呢?
;如果class没有定义构造函数、析构函数、拷贝构造函数、拷贝赋值运算符函数,那么C++内部会动创建一个默认的构造函数、析构函数、拷贝构造函数、拷贝赋值运算符函数。并且这些函数默认都是public且inline的。见条款30
示例:
如果你写下一个空类:
class Empty{}; //空类
这就好比,你写下了:
class Empty{public:Empty() { ... } //default构造函数Empty(const Empty& rhs) { ... } //Copy构造函数~Empty() { ... } //析构函数Empty& operator={const Empty& rhs) { ... } //copy assignment操作符
};
只有当这些函数被需要(被调用),它们才会被编译创建。
class Empty{}; //空类Empty e1; //调用e1的默认构造函数
Empty e2(e1);//调用e2的默认拷贝构造函数
e2 = e1; //调用e2的默认拷贝赋值运算符//程序结束
//调用e1与e2的默认析构函数
编译器为类生成的默认函数做了什么?
现在知道编译器为你写了函数,那么这些函数做了什么呢?
默认构造函数与默认析构函数
默认构造函数与默认析构函数主要是给编译器一个地方用来防止“隐藏幕后”的代码,像是调用基类和非静态成员变量的构造函数和析构函数
注意:编译器定义的默认析构函数是非virtual的,除非这个class的基类自身有virtual析构函数(这种情况下这个函数的虚属性(virtual)来自于基类)
默认拷贝构造函数和默认拷贝赋值运算符
默认拷贝构造函数和默认拷贝赋值运算符一样,都是在拷贝/对象赋值时将类的每一个非静态成员变量逐个拷贝到目标对象之中。
示例:
template<typename T>
class NamedObject
{public:NamedObject(const char* name, const T& value);NamedObject(const std::string& name, const T& value);...
private:std::string name;T objectValue;
};
这里声明了一个构造函数,所以编译器不再为它创建默认构造函数。而NamedObject即没有声明拷贝构造函数,也没有声明拷贝赋值运算符,所以编译器会生成默认的。下面是拷贝构造函数的用法:
NamedObject<int> no1("dongshao", 2);
NamedObject<int> no2(no1); //调用NamedObject<int>的默认拷贝构造函数
上面的no2对象调用默认的拷贝构造函数来拷贝no1对象,其中的操作有:
将no1对象的name数据成员拷贝给no对象的name数据成员(又因为name为string类型,所以最终会调用string的拷贝构造函数来拷贝name)
因为此程序中模板类型为int,所以objectValue为int内置类型,直接将no1对象的objectValue赋值给no2的objectValue
对于赋值运算符来说,其与拷贝构造函数一样,也是逐个将数据成员进行重新赋值。
拷贝赋值运算符的错误注意事项
虽然拷贝构造函数与拷贝赋值运算符用起来比较类似,但是有一种情况会导致出错,如:
template<typename T>
class NamedObject
{public://以下构造函数不再接受一个 const 名称,因为 nameValue//因为name变为了string引用类型,因此参数1位char*类型的构造函数就没有用了NamedObject(std::string& name, const T& value);... //假设并未声明 operator=
private:std::string& name; //string的引用类型const T objectValue; // const
};std::string newDog("Persephone");
std::string oldDog("Satch");
NamedObject<int> p(newDog, 2);
NamedObject<int> s(oldDog,36);p = s; //错误
上述“p=s”错误的原因:
name:因为name为引用类型了,我们知道引用一旦绑定就不可以改变引用指向,但是在此处拷贝赋值运算符中,我们将p的name引用从一开始指向于newDog又指向了oldDog,因此会发生错误。
objectValue:因为objectValue为const类型,因此在初始化之后其值就不可以改变了,此处将p的值从2改变为36因此会发生错误。
面对这个难题,C++ 的响应是拒绝编译那一行赋值动作。如果你打算在一个"内含引用成员"的 class 内支持赋值操作,你必须定义自己的拷贝赋值操作符。
在某些情况下,使用了系统提供的默认拷贝赋值运算符会出现错误。因此有些情况下我们不希望使用class提供的默认拷贝赋值运算符,那么就需要提供一种方法:
如果一个基类将拷贝赋值运算符声明为private,那么编译器就拒绝为派生类生成默认的拷贝赋值运算符。因为基类如果想使用这些函数,那么这些函数会相应的处理基类成份,但是基类是private的,所以不可以使用。
这种方法不仅适用于拷贝赋值运算符,对于构造函数、拷贝构造函数都同样有效
NOTE:
编译器可以暗自为class创建 default 构造、 copy 构造、copy 赋值操作符,以及析构函数。
总结
期待大家和我交流,留言或者私信,一起学习,一起进步!
Effective C++条款05:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls)相关推荐
- Effective C++:条款05:了解C++默默编写并调用哪些函数 (Know what functions C++ silently writes and calls.)...
编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 转载于:https://www.cnblogs.com/elite/arc ...
- EffectiveC++详解:条款05-了解C++默默编写并调用哪些函数
文章目录 条款05-了解C++默默编写并调用哪些函数 当我们写了一个空类,意味着什么 编译器什么时候拒绝生成拷贝赋值运算符 总结 @Author:CSU张扬 @Email:csuzhangyang@g ...
- Effective C++ 学习笔记 条款05 了解C++默默编写并调用了哪些函数
当写下一个空类时,编译器会为你合成一个拷贝构造函数.一个拷贝赋值运算符.一个析构函数,如没有声明其他的构造函数,编译器会合成一个默认构造函数.这些都是inline的public成员. 当类有一个引用成 ...
- [Effective C++读书笔记]005_条款05_了解C++默默编写并调用哪些函数
其实这一点在C++的基础类入门书,如C++ primer里面也有说过,不过很少有人去注意而已,作者把这一点提出来,是为了提醒我们. 这一条款的内容如下:就是说当你书写下面的[代码片段1]的时候,其实经 ...
- Effective C++记录(5):Know what functions C++ silently writes and calls.
了解C++默默编写并调用的哪些函数 1. 空类:默认构造函数.拷贝构造函数.析构函数.拷贝赋值操作符. 注意: a. 声明构造函数后,编译器将不再为该类常见默认构造函数. b. 当内含referenc ...
- 了解C++默默编写并调用哪些函数
在C++中,如果你写下 1 classEmpty{-}; 就相当于写下 1 classEmpty{ 2 public: 3 Empty();//default构造函数 4 Empty(constEmp ...
- Effective C++条款05:了解C++默默编写并调用哪些函数
class Empty{};class Empty{Empty(){};Empty(const Empty& rhs){};~Empty(){};Empty& operator=(co ...
- 条款05:了解C++默默编写并调用哪些函数
空类 如果你没有声明,编译器会为它声明一个default构造函数,copy构造函数,析构函数,赋值操作符. class Empty{}; //--------- class Empty { publi ...
- 条款5:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls)...
1.default costructor / copy constructor / copy assignment 者三者的区别? 特别是copy constructor & copy as ...
最新文章
- 重磅!我国建成首个自动驾驶封闭高速公路测试环境
- 智能车竞赛:提问与回答
- wprintf 和 wcout
- linux关于/etc/profile.d与/etc/profile的正确运用
- Linux学习-15-学习LVM逻辑卷
- c# 批量mqtt_Paho-MQTT C#接入示例
- RHEL5中实现各种服务的准备条件:
- Android局域网工具,NetX(局域网管理工具)
- Linux——虚拟机系统安装
- Idea中常用的快捷键(持续更新)
- 2022年信息安全工程师考试知识点:信息安全管理基础
- SiamRPN++详解:论文翻译
- 举个栗子!Tableau 技巧(131):用烛台图 Candlestick Chart 分析价格波动
- 白话机器学习-Encoder-Decoder框架
- 微擎服务器数据迁移 ,微擎通过迁移数据方式搬家换服务器换站点换域名【图文教程】
- 爬取起点小说总排行榜
- Android基础与手机历史
- Zeppelin打开定时调度
- VC++6.0英文原版+MSDN6.0下载(ISO格式)
- Feinstein Institute研究人员解码脑沟和白质区域的神经活动,预测手指运动和手部触觉刺激...
热门文章
- Linux命令_Note1
- 2020年8月20计算机大赛,NOI2020于8月17日正式开幕!今年哪些竞赛选手被保送清北计算机专业?...
- xgboost2 以及使用XGB.CV来进行调参
- 可变变量和不可变变量
- 【java】 【接口】【继承】【抽象类】案例 运动员和教练
- Spellchecker inspection helps locate typos and misspelling in your
- 小学生10以内加减运算练习系统(c语言)
- ModuleNotFoundError: No module named ‘xxx‘; ‘xxx‘ is not a package解决
- 我入门 Python 后总结的基础教程
- 西克推出LBR/LFR长距离非接触物位/液位传感器