• Effective C++ 笔记


    自己习惯C++

    1、C++为一个语言联邦

    STL,Template,智能指针,C++11

    2、尽量以const,enum,inline替换#define

    1)预处理在符号表中不存在,出现bug不好定位;目标码中也不会有多份Pia

    eg:

    #define Pia 3.14 (instead of--->) const double Pia = 3.14

    2)inline代替#define函数

    eg:

    #define MAX(a,b) f(

             if((a) > (b))

                       return (a)

             else

                       return (b)

             )

    template<class T>

    inline T Max(const T& a, const T& b)

    {...}

    3、尽量使用const

    1)区别不多说(const出现在星号左边,表示被指物是常量;出现在右边,表示指针本身是常量;出现在两边,被指物和指针都是常量)

    char str[] = "hello";

    char* p = str;

    const char* p = str;

    char* const p = str;

    const char* const p = str;

    2)const std::vector<int>::iterator iter = vec.begin();//like T* const;指针不能变,被指物可以变

    *iter = 10;//right

    iter++;//error

    遍历的时候,不能这样声明,可以使用下面这种

    如果想声明被指物不可变,使用const_iterator

    std::vector<int>::const_iterator citer = vec.begin();

    *citer = 10;//error

    citer++;//right

    3)函数参数const,不让内部改变参数属性;

    返回值const,一些可能的bug可以避免,如(a*b)=c的错误

    4)const成员函数:允许const属性的重载

    4、确认对象被使用前已经被初始化

    构造,析构,赋值

    5、了解C++默默编写并调用哪些函数

    构造函数(T()),析构(~T()),拷贝构造(T(const T& rhs)),复制函数(T &operator=(const T& rhs))

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

    拷贝构造,复制函数声明为private且不定义

    7、为多态基类声明virtual析构函数

    防止资源泄漏(保证子类析构函数被调用)

    8、别让异常逃离析构函数

    异常时终止或者吞下

    将可能抛出异常的代码提供给用户管理

    9、绝不在构造和析构过程中调用virtual函数

    构造和析构期间不要调用virtual函数,因为这类调用不会下降到子类的虚函数

    原因:

    子类构造前,先构造父类;父类调用虚函数,只能调用父类自己的函数,因为子类还没有构造;

    同理,子类析构,先析构自己,然后析构父类,当父类析构函数调用虚函数,不可能指向子类的虚函数,因为子类已经析构不存在了。

    PS:

    一个virtual函数,就有一个虚表;虚表是在编译期创建的。

    在执行期,根据虚表,程序找到虚函数实现体,实现多态

    10、令operator= 返回一个reference to *this

    eg:

    template <class T>

    T& operator=(const T& rhs)

    {

             ...

             return *this;

    }

    11、在operator=中处理“自我赋值”

    eg1:

    template <class T>

    T& operator=(const T& rhs)

    {

             if(this == &rhs)return *this;

             ...

             return *this;

    }

    eg2:

    copy-and-swap技术

    template <class T>

    T& operator=(const T& rhs)

    {

             if(this == &rhs)return *this;

             //copy-and-swap

             bitmap* pOrig = pb;

             pb = new bitmap(*rhs.pb);

             delete pOrig;

             //

             return *this;

    }

    12、复制对象时勿忘期每一个成分

    如果是子类赋值函数或者是复制构造函数,除了复制子类所有成员变量;

    需要适当调用父类的对应函数,父类不满足;父类也需要重新这些函数

    eg见代码effective12

    资源管理

    13、以对象管理资源

    构造函数获得资源,析构函数释放资源;

    使用智能指针封装:tr1::shared_ptr和auto_ptr。

    关于智能指针,见另外一片blog

    14、在资源管理类中小心copying行为

    15、在资源管理类中提够对原始资源的访问

    原始资源获取;

    显式转换安全

    隐式转换——对客户方便,不安全

    16、成对使用new和delete时采用相同形式

    new, delete

    new [], delete []

    17、以独立语句将newed对象置入智能指针

    eg:

    std::tr1::shared_ptr<T> pw(new T);

    processT(pw,test())

    代替

    processT(std::tr1::shared_ptr<T>(new T),test())

    防止test()出现异常,new T之后没有调用tr1::shared_ptr出现资源泄漏

    设计与声明

    18、让接口容易被正确使用,不易被误用

    类型一致性;

    shared_ptr防范跨DLL错误。

    19、设计class犹如设计type

    20、宁以pass-by-refenrence-to-const替换pass-by-value

    1)引用传递代替值传递(这个在Java,python中都已经默认使用。当然简单内置的类型还是value传递,其他都是引用传递了)

    2)高效,没有拷贝构造函数,析构函数执行

    3)STL使用pass-by-value比较适合,估计也是其中成员,而不是STL容器本身

    21、必须返回对象时,别妄想返回其reference

    1)绝对不要返回pointer或reference指向一个local stack对象,或者返回一个reference指向一个heap-allocated对象,

    或者返回pointer或reference指向一个local static 对象

    2)栈、堆、静态对象都不要作为引用返回

    22、将成员变量声明为private

    set***函数便于更改private变量,不易疏漏

    23、宁以non-member、non-friend替代member函数

    24、若所有参数且需类型转换,请为此采用non-member函数

    operator*(+,-等等)有隐式转换的左值,只能是全局函数,不能是成员函数

    25、考虑写一个不抛异常的swap函数

    实现

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

    不要提前定义,使用前定义

    27、尽量少做转型动作

    const_cast<T>:常量转换

    dynamic_cast<T>:继承关系转换

    reinterpret_cast<T>:eg point to int 转型为 int

    static_cast<T>:强迫隐式转换(无法const转为non-const,const_case<T>可以)

    详细见另外一个blog

    28、

  • 相关阅读:
    《活着》--余华
    《麦田里的守望者》--[美]杰罗姆·大卫·塞林格
    《平凡的世界》--路遥
    彩色照片转换为黑白照片(Color image converted to black and white picture)
    《戴尔·卡耐基传记》--[美]戴尔·卡耐基
    Maven的第一个小程序
    C# RabbitMQ优先级队列实战项目演练
    控制WinForm中Tab键的跳转
    C#模板引擎NVelocity实战项目演练
    C#隐藏手机号中间四位为*
  • 原文地址:https://www.cnblogs.com/2012harry/p/3968321.html
Copyright © 2020-2023  润新知