• Effective C++


    Effective C++

    1、只有int型的class static变量能在类中定义,其它类型(如double)只能在类中声明,在类外定义。

    class Student {
    private:
        // static int 可以在类中定义
        static const int age = 5;
    };
    
    class GamePlayer {
    private:
        // 非int型static变量只能在类中声明
        static const double NumTurns;
    
        // 下面这行代码会有编译错误
        // static const double NumTurns = 1.35f;
    };
    // 在类外定义
    const double GamePlayer::NumTurns = 1.35f;

    2、能不用宏定义,就尽量不用。如下例,将宏替换为函数,就不会存在此问题。

    #define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b))
    
    void f(int value) {}
    
    int main()
    {
        int a = 5, b = 0;
        CALL_WITH_MAX(++a, b);    // a被累加2次
        CALL_WITH_MAX(++a, b+10); // a被累加1次
    
        getchar();
        return 0;
    }

    3、迭代器的作用就像个T*指针。const ::iterator 类似 T* const,而 ::const_iterator 类似const T*。

        std::vector<int> vec;
    
        const std::vector<int>::iterator iter = vec.begin(); // iter类似T* const
        *iter = 10; // 正确,iter指向的是非const
        //++iter; // 错误,iter本身是const
    
        std::vector<int>::const_iterator cIter = vec.begin(); // cIter类似 const T*
        //*cIter = 10; // 错误,cIter指向的内容是const
        ++cIter; // 正确,cIter本身是非const

    4、operator类重载应当返回一个const变量。否则会产生如下问题。

    class Rational {};
    const Rational operator * (const Rational& lhs, const Rational &rhs);
    
    int main()
    {
        Rational a, b, c;
        // 因为返回值为const Rational,所以下行代码编译错误
        // (a*b) = c; 
    
        getchar();
        return 0;
    }

      返回cosnt还可以避免,如下错误:

        if (a*b == c) {}
    
        // 下面属于手误,少打了一个=,会发生编译错误
        //if (a*b = c) {}

    5、none-const operator[]应当返回一个none-const reference。否则,下述赋值代码就会失败。

      tb[0] = 'x'

    6、const函数,必须返回一个const变量。否则会产生如下问题。

    class CTextBlock {
    public:
        CTextBlock(char*p)
        {
            pText = p;
        }
        char& operator[] (std::size_t position) const
        {
            return pText[position];
        }
    private:
        char *pText;
    };
    
    int main()
    {
        const CTextBlock cctb("Hello");
        char *pc = &cctb[0];
        *pc = 'J'; // 现在有了'Jello'这样的数据
    
        getchar();
        return 0;
    }

     7、mutable在成员变量可以在const函数内被修改。

    8、当const、non-const函数有相同逻辑代码时,用non-const函数调用const函数的实现。

    char& operator[] (std::size_t position)
        {
            return const_cast<char&>(// 将cosnt属性移除
                static_cast<const CTextBlock>(*this)[position]
                );
        }

    9、编译器会为类声明构造函数、析构函数、copy构造函数、copy assignment函数。

       如果声明了一个构造函数,编译器不再创建default构造函数。

    class Empty {
    public:
        Empty(){}
        Empty(const Empty& rhs){}
        ~Empty(){}
        Empty& operator=(const Empty& rhs){}
    };

    10、如果你打算在一个“内含reference成员”的class内支持赋值操作(assignment),你必须定义自己的copy assignment函数。此种情况下,编译器不会生为你生成copy assignment函数。

      内含const成员也是一样的,编译器拒绝生成copy assignment。

      如果基类copy assignment定义为private,则编译器也拒绝为derived class生成copy assignment。

    11、把函数设置为private并不安全,因为member function、friend function还是可以访问private。

      将函数声明为priavte,而故意不实现它,现是解决方案。

      下在也是一种解决方案,但可能存在多重继承问题。

    class Uncopyable{
    protected:
        Uncopyable(){}
        ~Uncopyable(){}
    private:
        Uncopyable(const Uncopyable&);
        Uncopyable& operator =(const Uncopyable&);
    };
    
    class Entry : private Uncopyable{};

    12、每一个带有virtual函数的class都有一个vtable。

    13、将拥有non-virtual析构函数的类作为基类是非常愚蠢的。

    class SpecialString : public std::string // bad desing, string有个non-virtual destructor
    {
    public:
        SpecialString();
        ~SpecialString();
    
    private:
    
    };

      C++并没有你Java中的final class或C#中的sealed class机制。

    14、析构函数绝对不要吐出异常。如果destructor调用的函数可能抛出异常,那么捕获它,吞下它。

    15、不要在constructor、destructor中调用virtual函数。因为constructor、destructor中的virtual函数无效。

    16、auto_ptr当copy、assignment时,内部指针会变为NULL。

            auto_ptr更好的方案是引用计数指针,shared_ptr。引用计数无法打破环状引用。

      auto_ptr、shared_ptr调用的都是delete,而非delete[]。如果需要delete[],可以用scoped_array、shared_array。

    17、下述代码可能产生异常。

    procesWidge(std::tr1::shared_ptr<Widget>(new Widget()), priority());
  • 相关阅读:
    Python字符串前缀u、r、b、f含义
    Chrome文字识别插件:一键读图(OCR)
    GIT使用log命令显示中文乱码
    APP通用测试用例大全
    Python坑:bool是int的子类、列表循环中的变量泄露、lambda在闭包中会保存局部变量、重用全局变量
    Python代码覆盖率工具coverage使用教程
    Python坑:不要使用可变对象作为函数默认值、生成器不保留迭代过后的结果、嵌套列表创建、==和is的区
    Appium元素定位方法
    你可能不知道的几个外挂浏览器脚本
    浏览器扩展插件(一)
  • 原文地址:https://www.cnblogs.com/tekkaman/p/7900616.html
Copyright © 2020-2023  润新知