Effective C++ 学习笔记
基于此文档
http://wenku.baidu.com/view/ef989106e87101f69e3195db.html
条款13:以对象管理资源
目标:为确保资源被释放
1.获得资源后立即放进管理对象
2.管理对象运用析构函数确保资源被释放
做法:
之前
void f() {Investment *pInv = createInvestment(); // call factory function... // use pInvdelete pInv; // release object }
之后
void f() {std::auto_ptr<Investment> pInv(createInvestment()); }
关于std::auto_ptr和std::tr1::shared_ptr用法不再叙述
条款14:在资源管理类中小心coping行为
class Lock { public:explicit Lock(Mutex *pm): mutexPtr(pm){ lock(mutexPtr); } // acquire resource~Lock() { unlock(mutexPtr); } // release resourceprivate:Mutex *mutexPtr;};
coping行为
Lock ml1(&m); // lock mLock ml2(ml1);
问题:“当一个RAII对象被复制,会发生什么事?”
选择做法:
1.禁止复制
class Lock: private Uncopyable { // prohibit copying — see public: // Item 6... // as before};
2.(最为普遍方法)利用std::tr1::shared_ptr的删除器做引用计数(当计数为0时调用的函数,但不删除指针)
class Lock { public:explicit Lock(Mutex *pm) // init shared_ptr with the Mutex: mutexPtr(pm, unlock) // to point to and the unlock func{ // as the deleterlock(mutexPtr.get()); // see Item 15 for info on "get"} private:std::tr1::shared_ptr<Mutex> mutexPtr; // use shared_ptr };
3.深拷贝资源,但不用时要做删除动作
4.利用auto_ptr做资源拥有权的转移
条款15:在资源管理类中提供对原始资源的访问
如下代码
std::tr1::shared_ptr<Investment> pInv(createInvestment()); // from Item 13int daysHeld(const Investment *pi); // return number of daysint days = daysHeld(pInv); // error!int days = daysHeld(pInv.get());
两种方式:
1.显示转换:get方法就是显示转换
class Font { // RAII class public:... // C API doesFontHandle get() const { return f; }private:FontHandle f; // the raw font resource... };changeFontSize(f.get(), newFontSize); // explicitly convert
2.隐式转换
class Font {public:...operator FontHandle() const { return f; } // implicit conversion function... };changeFontSize(f, newFontSize); // implicitly convert
显然各有优缺点,但显示转换不易被误用,如std: string的显示转换方法
条款17:以独立语句将newd对象置入智能指针
int priority();void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);
如何传参的问题:
重点:保证传入的指针在异常的时候可以释放资源
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
以上做法可能有错误,如果执行顺序如下,而priority函数发生了错误,那么内存无法释放
Execute "new Widget".
Call priority.
Call the tr1::shared_ptr constructor.
保险的做法,在外部声明
std::tr1::shared_ptr<Widget> pw(new Widget); // store newed objectprocessWidget(pw, priority()); // this call won't leak
第四章:设计与声明
这一章大多与设计有关
条款18:让接口容易被正确使用,不易被误用
让接口更易被理解和使用
之前:
class Date { public:Date(int month, int day, int year);... };
以类代替(请勿模仿,任何事物防不胜防,看需求而定)
struct Day { struct Month { struct Year {explicit Day(int d) explicit Month(int m) explicit Year(int y):val(d) {} :val(m) {} :val(y){}int val; int val; int val;}; }; };class Date {public:Date(const Month& m, const Day& d, const Year& y);...};Date d(30, 3, 1995); // error! wrong types Date d(Day(30), Month(3), Year(1995)); // error! wrong types Date d(Month(3), Day(30), Year(1995)); // okay, types are correct
条款 21:必须返回对象时,别妄想返回其reference
拒绝一下两种写法,c#和java的开发者一定很不习惯
const Rational& operator*(const Rational& lhs, // warning! bad code!const Rational& rhs){Rational result(lhs.n * rhs.n, lhs.d * rhs.d);return result; }const Rational& operator*(const Rational& lhs, // warning! more badconst Rational& rhs) // code!{Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);return *result; }
必须要返回对象是,请返回一个新对象
inline const Rational operator*(const Rational& lhs, const Rational& rhs){return Rational(lhs.n * rhs.n, lhs.d * rhs.d); }
条款 22:将成员变量声明为private
真的没什么好讲的,学过c#和java的人都知道
class AccessLevels {public:...int getReadOnly() const { return readOnly; }void setReadWrite(int value) { readWrite = value; }int getReadWrite() const { return readWrite; }void setWriteOnly(int value) { writeOnly = value; }private:int noAccess; // no access to this intint readOnly; // read-only access to this intint readWrite; // read-write access to this intint writeOnly; // write-only access to this int};
条款 23:宁以non-member、non-friend替换member函数
class WebBrowser { public:...void clearCache();void clearHistory();void removeCookies();//void clearBrowser(WebBrowser& wb)//{// wb.clearCache();// wb.clearHistory();// wb.removeCookies();//}...}; void clearBrowser(WebBrowser& wb) {wb.clearCache();wb.clearHistory();wb.removeCookies(); }
将便利函数放在外部,不要为类添加太多的类成员(意思就是只添加必要的),基本属于设计问题
条款 24:若所有参数皆需类型转换,请为此采用non-member函数
如下示例代码
class Rational { public:Rational(int numerator = 0, // ctor is deliberately not explicit;int denominator = 1); // allows implicit int-to-Rational// conversionsint numerator() const; // accessors for numerator andint denominator() const; // denominator — see Item 22const Rational operator*(const Rational& rhs) const; private:... };
其提供了隐式转换功能:
Rational oneEighth(1, 8); Rational oneHalf(1, 2);Rational result = oneHalf * oneEighth; // fineresult = result * oneEighth; // fine
更加贪婪的做法
result = oneHalf * 2; // fine result = 2 * oneHalf; // error!
为了支持2的隐式转换,做法是实现一个non-member的操作符重载
const Rational operator*(const Rational& lhs, // now a non-memberconst Rational& rhs) // function{return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator());} Rational oneFourth(1, 4);Rational result;result = oneFourth * 2; // fineresult = 2 * oneFourth; // hooray, it works!
记得是所有参数
转载于:https://www.cnblogs.com/Clingingboy/archive/2011/07/27/2118806.html
Effective C++ 学习笔记相关推荐
- Effective C++ 学习笔记 第七章:模板与泛型编程
第一章见 Effective C++ 学习笔记 第一章:让自己习惯 C++ 第二章见 Effective C++ 学习笔记 第二章:构造.析构.赋值运算 第三章见 Effective C++ 学习笔记 ...
- Java:Effective java学习笔记之 考虑实现Comparable 接口
Java 考虑实现Comparable 接口 考虑实现Comparable 接口 1.Comparable接口 2.为什么要考虑实现Comparable接口 3.compareTo 方法的通用约定 4 ...
- Effective C++学习笔记(Part Five:Item 26-31)
2019独角兽企业重金招聘Python工程师标准>>> 最近终于把effectvie C++仔细的阅读了一边,很惊叹C++的威力与魅力.最近会把最近的读书心得与读书笔记记于此, ...
- Effective C++学习笔记(Part One:Item 1-4)
2019独角兽企业重金招聘Python工程师标准>>> 最近终于把effectvie C++仔细的阅读了一边,很惊叹C++的威力与魅力.最近会把最近的读书心得与读书笔记记于此,必备查 ...
- 【Effective C++ 学习笔记】
条款02:尽量以const,enum,inline替换 #define #define定义的常量也许从未被编译器看见,也许在编译器开始处理源码之前它就被预处理器移走了: #define不重视作用域,不 ...
- Effective C++学习笔记——构造/析构/拷贝运算
条款9:决不再构造和析构过程中调用virtual函数,包括通过函数间接调用virtual函数. 应用:想在一个继承体系中,一个derived class被创建时,某个调用(例如生成相应的日志log)会 ...
- Effective C# 学习笔记(八)多用query语法,少用循环
对于C#的query查询语法,其可读性和可维护性要比原来的loop操作好得多 例子: 同样是创建个二维元组,并对其元组按到原点的距离进行倒序排序,用query 语法的表达形式要比原始的循环做法来的更易 ...
- Effective Java 学习笔记 1
Item 1: Consider static factory methods instead of constructors (多考虑使用静态工厂方法而不是构造方法) 使用静态工厂方法有以下几点好 ...
- Effective C++ 学习笔记(11)
确定基类有虚析构函数 class A{public: A() { cout<<"A constructor"<<endl; }~A() { cout< ...
最新文章
- python空类型-在Python中__________表示空类型。
- 启动Mysql时发生的一个关于PID文件错误问题
- 抢先看!Kubernetes v1.21 新特性一览
- java怎样生成32位全是整形的主键_用java生成32位全球唯一的id编号
- C++指针与数组的对比
- 4: Consolidating Datasets ( Challenge: Data Munging Using The Command Line)
- [zhuan]asp.net程序性能优化的七个方面 (c#(或vb.net)程序改进)
- Origin画甘特图-II
- 数据包络分析DEA有哪些指标?
- 软件测试中期答辩,毕业论文中期答辩报告.doc
- 【AAAI 2021】全部接受论文列表(六)
- matlab 牛顿冷却定律,传热学MATLAB度分布大作业完整版.doc
- 大型即时通讯系统微信、陌陌架构分析全记录!
- 微信支付不靠谱 星巴克喝一杯咖啡被刷掉一千多
- 在线K歌又现新模式 音遇APP能否站稳脚跟?
- 工控主板定制ARM9选择思路
- 网络核心之分组交换与电路交换
- “正交阵”与“特征值和特征向量”
- httpclient3.1的relaseConnection的misunderstand
- Seo:如何搜索搜索网站热点关键词和网站长尾关键词的特点和优势
热门文章
- 怎么理解python的__init___理解Python中super()和__init__()方法
- vim实用技巧-笔记(第九章)
- (转载)输出文件的指定行
- 岭回归与Lasso回归
- Python:SMOTE算法——样本不均衡时候生成新样本的算法
- slplunk原始数据和索引数据大小比较
- Apache Samza流处理框架介绍——kafka+LevelDB的Key/Value数据库来存储历史消息+?
- Mac NIFI 安装
- 在CentOS上安装Python
- 用vc++如何得到汉字的Unicode编码?