zoukankan      html  css  js  c++  java
  • Effective C++ 笔记(1)

    1.       让自己习惯C++

     条款1: C++为一个语言联邦

    条款2: 尽量以const, enum, inline替换 #define

    条款3: 尽可能使用const

    条款4: 确定对象被使用前已先被初始化

     

    2.       构造/析构/赋值运算

    条款5: 了解C++默默编写并调用哪些函数

    条款6: 若不想使用编译器自动生成的函数,就该明确拒绝

    可以将copy constructor or copy assignment声明为private,且不定义.


    条款7: 为多态基类生命能够virtual析构函数

    条款8: 别让异常逃离析构函数

    析构函数抛出异常会导致不明确行为,在析构函数中捕捉.

     

    条款9: 绝不在构造和析构过程中调用virtual函数.

     class baseclass

    {

             baseclass()

             {

                       func(); /*此时对象类型为baseclass, 调用的是baseclass中的func, 因为derivedclass变量尚未初始化,所以不可能调用derivedclass中的函数(会调用derivedclass中的变量)*/

             }

             virtual void func(void) const

             {

             }

    };

    条款10: operator= 返回一个reference to *this

    条款11: operator= 中处理自我赋值

    确定操作对象是同一对象时,其行为仍然正确.


    条款12: 复制对象时,勿忘其每一个成分


     3.       资源管理

    条款13. 以对象管理资源

    使用RAII对象,他们在构造函数中获得资源并在析构函数中释放资源,两个常被使用的RAII class tr1::shared_ptrauto_ptr.


    条款14: 在资源管理类中小心copying行为

    shared_ptrauto_ptr管理的是heap-based资源,有时候并不适合管理其他资源,所以你需要建立自己的资源管理类.

    using namespace System;

    using namespace  System::Threading;

     class Lock

    {

    public:

             explicit Lock(Mutex *pm)

                       : mutexptr(pm)

             {

                       lock(mutexptr);

             }

     

             ~Lock()

             {

                       unlock(mutexptr);

             }

    private:

             Lock(const Lock &); //禁止复制

             Mutex *mutexptr;

    };

    可以改写为:

    class Lock

    {

    public:

             explicit Lock(Mutex *pm)

                       : mutexptr(pm, unlock) /*shared_ptr允许指定删除器,一般为一个函数或者函数对象,当引用次数为0时,自动调用删除器,auto_ptr无,第二个参数默认为NULL*/

             {

                       lock(mutexptr.get()); //获得资源

             }

     private:

             Lock(const Lock &); //禁止复制

             std::tr1::shared_ptr<Mutex> mutexptr;

    };

    条款15: 在资源管理类中提供对原始资源的访问

    如同shared_ptrauto_ptr,调用get()函数返回原始指针,或者使用隐式转换,将资源管理类转换为原始指针 operator ptr();


    条款16: 成对使用newdelete, 要采取相同形式

    new – delete, new [] – delete []


    条款17: 以独立语句将newed对象置入只能指针

    func(std::tr1::shared_ptr<myclass>(new myclasss), func2());

    也许编译器执行顺序为new, func2, call shared_ptr constructor, 如果func2异常,则new指针遗失且内存泄露.所以独立将new对象置入只能指针.

    std::tr1::shared_ptr<myclass> ptr(new myclasss);

    func(ptr, func2());

     

    4.       设计与声明

    条款18: 让接口容易被正确使用, 不易被误用

    条款19: 设计class犹如设计type

    条款20: 宁以pass-by-reference-to-const替换pass-by-value

    pass-by-value可能被切割,而引用往往以指针实现,pass by reference通常意味这真正传递的是指针,所以内置对象一般pass-by-value效率高些,也适用于STL的迭代器和函数对象,因为习惯上他们设定为passed by value.

     

    条款21: 必须返回对象时,不要返回其reference

    返回其副本,不能是局部变量的引用(销毁)local static(同一内存)变量或者new(无法delete).

     

    条款22: 将成员变量声明为private

    条款23: 宁以non-member, non-friend替换member函数

    条款24: 若所有参数皆需类型转换, 请为此采用non-member函数

    class rational

    {

    public:

             const rational operator *(const rational &rhs) const;

    }

    rational result;

    rational onehalf;

    result = onehalf*2; //ok, result.operator *(2);

    result = 2*onehalf; //error, 2.operator *( result);

    即使

    class rational

    {

    public:

    rational(int); //隐式转换

             const rational operator *(const rational &rhs) const;

    }

    result = 2*onehalf; //error,因为只有当参数被列于参数列内,参数才可以进行隐式转换.

    所以将operator *设为non-member函数

    const rational operator *( const rational &lhs,const rational &rhs);

     

    条款25: 考虑写出一个不抛异常的swap函数

    如果在你的class中需要改写swap,那么也该提供一个non-member swap来调用前者.

    class rational

    {

    public:

             void swap(rational &)

             {

                       using std::swap;

                       ...

             }

    };

    namespace std

    {

             template<> void swap<rational>(rational &a, rational &b)

             {

                       a.swap(b);

             }

    }

    如果rationaltemplate

    template <class T>class rational

    {

    public:

             void swap(rational &)

             {

                       using std::swap;

                       ...

             }

    };

    namespace std

    {

             template<class T> void swap(rational<T> &a, rational<Y> &b) /*重载, 但是error,可以特化std里面的templates,但是不可以添加新的templatesclassedfunctions或其他任何东西, std里面的东西完全由C++标准委员会决定.*/

             {

                       a.swap(b);

             }

    }

    namespace rationalstuf

    {

             template <class T>class rational

             {

             public:

                       void swap(rational &)

                       {

                                using std::swap;

                                //...

                       }

             };

             template<class T> void swap(rational<T> &a, rational<T> &b) //ok

             {

                       a.swap(b);

             }

    }

     

    5.       实现

    条款26: 尽可能延后变量定义式的出现时间

    条款27: 尽量少做转型动作

    const_cast<T>(expression) //const转换为non-const

    dynamic_cast<T>(expression) //安全像下转型,baseclass change to derivedclass

    reinterpret_cast<T>(expression) //执行低级转换

    static_cast<T>(expression) //强迫隐式转换

    使用C++ stytle转型,不要使用就是转型,避免使用dynamic_cast

     

    条款28: 避免返回handles指向对象内部成分

    class myclass

    {

    public:

             int &get(){return m_i;}

    private:

             int m_i;

    };

    降低对象封装性,而且有可能使用handle时,对象可能被析构.

     

    条款29: 为"异常安全"而努力

    当异常抛出时,不泄漏任何资源,不允许数据破换.

     

    条款30: 透彻了解inlining的里里外外

    inlinetemplate都是编译器行为,被置于头文件中,因为inlining将函数调用替换为本体,所以需要知道函数定义,同样,template需要实例化也需要知道定义.

    virtual函数会让inline落空,因为virtual是运行期决定,而inline是编译时决定.

    inline无法随程序库的升级而升级,客户程序必须重新编译.

     

    条款31: 将文件间的编译依存关系降至最低

    相依于声明式,不要相依于定义式.

  • 相关阅读:
    32位与64位操作系统到底有什么区别呢?
    chr()、unichr()和ord()
    Python map filter reduce
    as3.0横向渐变发光字
    Python time format
    Python 使用sys重定向
    as3.0给文字加纹理效果
    my first python
    字符编码(转)
    SWFTOOLS学习笔记一(转)
  • 原文地址:https://www.cnblogs.com/zengyou/p/2195593.html
Copyright © 2011-2022 走看看