基于此文档

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函数发生了错误,那么内存无法释放

  1. Execute "new Widget".

  2. Call priority.

  3. 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++ 学习笔记相关推荐

  1. Effective C++ 学习笔记 第七章:模板与泛型编程

    第一章见 Effective C++ 学习笔记 第一章:让自己习惯 C++ 第二章见 Effective C++ 学习笔记 第二章:构造.析构.赋值运算 第三章见 Effective C++ 学习笔记 ...

  2. Java:Effective java学习笔记之 考虑实现Comparable 接口

    Java 考虑实现Comparable 接口 考虑实现Comparable 接口 1.Comparable接口 2.为什么要考虑实现Comparable接口 3.compareTo 方法的通用约定 4 ...

  3. Effective C++学习笔记(Part Five:Item 26-31)

    2019独角兽企业重金招聘Python工程师标准>>>  最近终于把effectvie C++仔细的阅读了一边,很惊叹C++的威力与魅力.最近会把最近的读书心得与读书笔记记于此, ...

  4. Effective C++学习笔记(Part One:Item 1-4)

    2019独角兽企业重金招聘Python工程师标准>>> 最近终于把effectvie C++仔细的阅读了一边,很惊叹C++的威力与魅力.最近会把最近的读书心得与读书笔记记于此,必备查 ...

  5. 【Effective C++ 学习笔记】

    条款02:尽量以const,enum,inline替换 #define #define定义的常量也许从未被编译器看见,也许在编译器开始处理源码之前它就被预处理器移走了: #define不重视作用域,不 ...

  6. Effective C++学习笔记——构造/析构/拷贝运算

    条款9:决不再构造和析构过程中调用virtual函数,包括通过函数间接调用virtual函数. 应用:想在一个继承体系中,一个derived class被创建时,某个调用(例如生成相应的日志log)会 ...

  7. Effective C# 学习笔记(八)多用query语法,少用循环

    对于C#的query查询语法,其可读性和可维护性要比原来的loop操作好得多 例子: 同样是创建个二维元组,并对其元组按到原点的距离进行倒序排序,用query 语法的表达形式要比原始的循环做法来的更易 ...

  8. Effective Java 学习笔记 1

    Item 1: Consider static factory methods instead of constructors  (多考虑使用静态工厂方法而不是构造方法) 使用静态工厂方法有以下几点好 ...

  9. Effective C++ 学习笔记(11)

    确定基类有虚析构函数 class A{public: A() { cout<<"A constructor"<<endl; }~A() { cout< ...

最新文章

  1. python空类型-在Python中__________表示空类型。
  2. 启动Mysql时发生的一个关于PID文件错误问题
  3. 抢先看!Kubernetes v1.21 新特性一览
  4. java怎样生成32位全是整形的主键_用java生成32位全球唯一的id编号
  5. C++指针与数组的对比
  6. 4: Consolidating Datasets ( Challenge: Data Munging Using The Command Line)
  7. [zhuan]asp.net程序性能优化的七个方面 (c#(或vb.net)程序改进)
  8. Origin画甘特图-II
  9. 数据包络分析DEA有哪些指标?
  10. 软件测试中期答辩,毕业论文中期答辩报告.doc
  11. 【AAAI 2021】全部接受论文列表(六)
  12. matlab 牛顿冷却定律,传热学MATLAB度分布大作业完整版.doc
  13. 大型即时通讯系统微信、陌陌架构分析全记录!
  14. 微信支付不靠谱 星巴克喝一杯咖啡被刷掉一千多
  15. 在线K歌又现新模式 音遇APP能否站稳脚跟?
  16. 工控主板定制ARM9选择思路
  17. 网络核心之分组交换与电路交换
  18. “正交阵”与“特征值和特征向量”
  19. httpclient3.1的relaseConnection的misunderstand
  20. Seo:如何搜索搜索网站热点关键词和网站长尾关键词的特点和优势

热门文章

  1. 怎么理解python的__init___理解Python中super()和__init__()方法
  2. vim实用技巧-笔记(第九章)
  3. (转载)输出文件的指定行
  4. 岭回归与Lasso回归
  5. Python:SMOTE算法——样本不均衡时候生成新样本的算法
  6. slplunk原始数据和索引数据大小比较
  7. Apache Samza流处理框架介绍——kafka+LevelDB的Key/Value数据库来存储历史消息+?
  8. Mac NIFI 安装
  9. 在CentOS上安装Python
  10. 用vc++如何得到汉字的Unicode编码?