zoukankan      html  css  js  c++  java
  • 【effective c++】实现

    1.尽可能延后变量定义式的出现时间

    应该延后变量的定义,直到能够给它初值为止.这样不仅能够避免构造(和析构)非必要对象,还可以避免无意义的default构造行为

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

    Widget w;
    for (int i = 0; i < n; ++i)
    {
        w = value;
        //...
    }

    方法B:n个构造函数 + n个析构函数

    for (int i = 0; i < n; ++i)
    {
        Widget w(value);
        //...
    }

    通常采用方法B,方法A中w的作用域比做法B大

    2.尽量少做转型动作

    const_cast通常用来将对象的常量性移除,它是唯一有此能力的c++-style转型操作符

    dynamic_cast主要用来执行安全向下转型,比如将指向基类的指针或引用类型转换为指向派生类的指针或引用,dynamic_cast的许多实现版本执行速度相当慢,在注重效率的代码中要尽量避免dynamic_cast

    static_cast用来强迫隐式转换,比如将non-const对象转为const对象,但它无法将const转为non-const

    class Window
    {
    public:
        Window()
        {
            width = 2;
            height = 2;
        }
        virtual void onResize()
        {
            width = 10;
        }
    
        int width;
        int height;
    };
    
    class SpecialWindow :public Window
    {
    public:
        virtual void onResize()
        {
            /*
            在当前对象的base class成分的副本上调用Window::onResize,然后在当前对象身上执行SpecialWindow专属动作。如果Window::onResize
            修改了对象内容,当前对象没被改动,改动的是副本,然后SpecialWindow::onResize内如果也修改对象,当前对象会被改动
            */
            //若只是想在派生类中调用基类版本的onResize函数,用下面的代码
            //Window::onResize();
            static_cast<Window>(*this).onResize();
            height = 3;
        }
    };
    
    int main()
    {
        SpecialWindow sw;
        sw.onResize();
        cout << sw.width << " " << sw.height << endl;//输出2 3
    
        system("pause");
        return 0;
    }

    3.避免返回handles(reference、指针、迭代器)指向对象内部成分

    遵守这个条款可增加封装性防止handles指向不存在的对象

    4.为"异常安全"而努力

    异常安全函数提供以下三个保证之一:

    基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态下,但具体哪个状态不可预料

    强烈保证:如果异常被抛出,程序会回复到调用函数之前的状态,能够通过copy-and-swap实现,但强烈保证并非对所有函数都可实现或具备现实意义

    不抛掷(nothrow)保证:承诺绝不抛出异常,因为它们总是能够完成它们原先承诺的功能。作用于内置类型(如int,指针等)身上的所有操作都提供nothrow保证.

    5.透彻了解inlining的里里外外

    inline函数背后的整体思想是,将对此函数的每一个调用都以函数本体替换,免除函数调用成本,但过度热衷inlining会造成程序体积太大

    inline只是对编译器的一个申请,不是强制命令。这项申请可以隐式提出,也可以明确提出。隐式方式是将函数定义于class定义式内(包括成员函数和友元函数)

    inline函数无法随着程序库的升级而升级,如果f是程序库内的一个inline函数,客户将f函数本体编进其程序中,一旦程序库设计者决定改变f,所有用到f的客户端程序都必须重新编译。而如果f是non-inline函数,一旦它有任何修改,客户端只需要重新连接就好,远比重新编译的负担少很多。

    大部分编译器拒绝将太过复杂(带有循环或递归)的函数inlining,而所有对virtual函数的调用都会使inlining落空.virtual意味着等待,直到运行期才确定调用哪个函数,inline意味着执行前,先将调用动作替换为被调用函数的本体

    6.将文件间的编译依存关系降至最低

    6.1. 如果使用object references或object pointers可以完成任务,就不要使用objects.你可以只靠一个类型声明式就定义出指向该类型的references和pointers;但如果定义某类型的objects,就需要用到该类型的定义式

    6.2. 如果能够,尽量以class声明式替换class定义式.当你声明一个函数而它用到某个class时,你并不需要该class的定义,纵使函数以by value方式传递该类型的参数(或返回值)亦然

    6.3. 为声明式和定义式提供不同的头文件

  • 相关阅读:
    第一个java程序和注释
    hadoop map端join
    hadoop wordcount入门
    hadoop reduce端联结
    hadoop streaming的使用
    HDU5752 Sqrt Bo
    L2-008 manacher 的应用
    L3-001 凑零钱
    L2-001 紧急救援
    如何在ubuntu下安装go开发环境
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/5861896.html
Copyright © 2011-2022 走看看