惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园_首页
M
MIT News - Artificial intelligence
雷峰网
雷峰网
GbyAI
GbyAI
博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
S
SegmentFault 最新的问题
H
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 【当耐特】
V
Visual Studio Blog
月光博客
月光博客
G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
云风的 BLOG
云风的 BLOG
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
有赞技术团队
有赞技术团队

博客园 - liuchen

我回来了 《全景探秘游戏设计艺术》读后感之引子 长连接和短连接 这不科学 —— 读《死亡之旅》 windows 64位 luajava编译 Effective C++ 读书笔记(45-50):杂项讨论 Effective C++ 读书笔记(35-44):继承关系与面向对象设计 Effective C++ 读书笔记(29-34):类与函数之实现 Effective C++ 读书笔记(18-28):类与函数之设计和声明 Effective C++ 读书笔记(5-10):内存管理 Effective C++ 读书笔记(0-4) - liuchen 读《msyql完全手册》之三:管理与开发 读《msyql完全手册》之二:数据库使用 读《msyql完全手册》之一:介绍和安装 js中的定时器 php中readdir关于时间路径排序的代码 linux 配置服务器 Windows下配置SVN (Subversion) 转载 该适当的总结了
Effective C++ 读书笔记(11-17):构造析构和赋值函数 - liu...
liuchen · 2009-10-14 · via 博客园 - liuchen

Item11--如果class内动态置有内存,请为此class声明一个copy constructor和一个assignment运算符

也就是说,class内有一个指针,使用new来动态申请内存的情况下,默认的copy constructor和assignment运算符是浅拷贝(bitwise copy),也即直接拷贝指针的值,可能会有内存泄露的危险
String a("hello");{String b("hello");b=a;}当b=a,b原来的内容变成野指针,当b结束作用域后a的内容也被删除。这真是灾难
所以条款11告诉我们:class内有指针需要申请内存,则自己撰写拷贝构造和赋值函数,避免内存泄露和异常。

Item 12 -- 在constructor中尽量以initialization动作取代assignment动作

原因:
1,const、reference只能通过初始化列表进行初始化
2,从效率角度。对象的构造分成两阶段:初始化data member(可以根据初始化列表进行,无则初始化为0等默认值),执行被调用的构造函数。所以执行assignment实际执行了两次赋值。
3,基本类型的non-const, non-reference对象,初始化和赋值之间没有2所说的区别

Item 13 -- initialization中的members初始化次序应该和其在class内的声明次序相同

原因也很容易理解:编译器构造和析构的顺序是相反的,编译器不可能针对初始化列表中的顺序进行初始化,否则重载不同初始化顺序的构造函数会让编译器头晕的。编译器内部确定是按照class内的声明次序,如果初始化列表不同,很可能初始化列表的数据会错误。
核心:先按class内声明成员默认赋值,然后调用初始化参数列表进行初始化。

Item 14 --  总是让base class拥有virtual destructor

原因很容易理解:基类指针指向具体派生类,delete基类指针的时候,需要虚函数进行多态。
tip:如果析构函数不是虚的,那么基类和派生类的析构都要调用 ,先调用派生,再调用基类
tip2
:虚函数要占用class空间,要综合考量

Item 15 -- 令operator= 传回"*this的reference"

原因:objA = objB = objC这种连续的重载=号行为
e.g.

String& String::operator =(const String&rhs)
{

return *this;
}

Item16-- 在operator=中为所有的data members设定(赋值)内容

原因:编译器会默认为你生成一个operator=,采用bitwise,所以最好都是自己写一个
注意点:继承机制的引入,Base中的私有成员Derived对象无法访问
要么 Base::operator=(rhs),要么staqtic_cast<Base&>(*this) = rhs两种方式解决

Item17 -- 在Operator=中检查是否"自己赋值给自己"

一般采用的方法:

C& C::operator=(const C&rhs)
{
if(this==&rhs) return * this;
}

这主要是针对如何判断对象相等的问题,这里采用的是地址相等的方法