• EC++学习笔记(五) 实现


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

    尽可能延后变量的定义,知道非得使用该变量的前一刻为止
    方法A:

    Widget W;
    for (int i = 0; i < n; ++i) {
        W = ...
    }

    方法B:

    for (int i = 0; i < n; ++i) {
        Widget W;
    }

    方法A:一个构造函数 + 一个析构函数 + n个赋值操作
    方法B:n个构造函数 + n个析构函数

    条款27:尽量少做转型
    const_cast<T>(expression):唯一可以将对象的常量性移除(将 const 转 non-const)
    dynamic_cast<T>(expression):除单元测试可以使用以外,其余情况禁用
    reinterpret_cast<T>(expression): 指针类型的转型,较少使用
    static_cast<T>(expression):显式转型,最常用,c++中禁用C语言旧式转型方法

    强制函数调用使用虚函数的特定版本(规避多态执行),请使用作用域操作符:

    virtual void Derived::func(int x) {
        ...
        Base::func(x);    //强制使用Base类里的函数
    }

    派生类虚函数调用基类版本时,必须显式使用作用域操作符

    条款28:避免返回handle(reference、pointer、iterator)指向对象内部成分(注意不是函数体内的local变量)

    遵守这条规则,可以增加封装性,规避潜在风险

    条款29:为"异常安全"而努力是值得的
    class PrettyMenu{
    public:
        void ChangeBackground(std::istream& imgsrc);    //改变图像背景
    private:
        Mutex* mutex;        //互斥器
        Image* image;        //目前的图像背景
        int    imageChange;    //背景图像被改变的次数
    };
    
    void PrettyMenu::ChangeBackground(std::istream& imgsrc) {
        lock(&mutex);                //取得互斥器
        delete image;                //摆脱旧的背景图像
        ++imageChange;                //改变图像更改次数
        image = new Image(imgsrc);    //安装新的背景图像
        unlock(&mutex);                //释放互斥器
    }

    上面函数没有异常安全性,因为异常安全性函数:
    不泄漏任何资源:上述代码中当 new Image 发生异常时,互斥器就永远不会释放
    不允许数据败坏:上述代码中当 new Image 发生异常时, imageChange已经被累加,其实新的背景图像并没有成功安装

    任何使用动态内存的东西(例如所有STL容器)如果无法找到足够内存满足需求,通常会抛出一个 bad_alloc 异常
    对于上述代码,我们使用对象来管理资源(image和mutex):

    class PrettyMenu{
    public:
        void ChangeBackground(istream& imgsrc);
    private:
        std::shared_ptr<Image> bgImage;
    };
    
    void PrettyMenu::ChangeBackground(std::istream& imgsrc) {
        Lock m1(&mutex);
        bgImage.reset(new Image(imgsrc));
        ++imageChange;
    }
    条款30:透彻了解 inline 的里里外外

    类的成员函数在类内定义时该函数默认为 inline 函数
    inline 函数通常位于头文件内
    一个表面看似 inline 的函数是否真的是 inline,取决你的 build environment,主要取决于编译器
    inline 是个申请,编译器可以加以忽略,大部分编译器拒绝将太过复杂的函数、virtual 函数 inline
    编译器通常不对"通过函数指针而进行的调用"实施 inline

    可以联想 自定义比较函数comp通过函数指针传递给sort,实际上指针调用未inline,故sort比qsort快
    将大多数 inline 限制在小型(小于10行)被频繁调用的函数身上(注意构造函数、析构函数、虚函数、递归函数通常不能 inline)

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

    如果一个foo.cc文件,则最佳的头文件排序方式:(可有效减少隐藏依赖)

    foo.h(即源文件对于的头文件)
    C语言标准库头文件
    c++语言标准库头文件
    windows头文件(或者unix头文件)
    MFC头文件(或者posix头文件)
    第三方项目头文件(例如Google开源代码头文件、boost头文件)
    本项目其他头文件

    使用pimpl(pointer to implementation)手法,将接口与实现分离,以"声明的依存性" 替换 “定义的依存性”

  • 相关阅读:
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(4月19日)
    2016年小升初海淀区全部初中排名分析
    LVM Linear vs Striped Logical Volumes
    Spring Data Redis实现消息队列——发布/订阅模式
    Redis Pubsub命令用法
    mysql 截取身份证出生日期
    MA均线组合
    Eclipse代码格式化规范
    JSON Web Token实际应用
    JSON Web Token单点登录设计
  • 原文地址:https://www.cnblogs.com/wwwjieo0/p/3443627.html
Copyright © 2020-2023  润新知