Effective C++ 笔记 第一部分 让自己习惯C++

1.视C++为一个语言联邦(View C++ as a federation of languages)

C++可分为4个主要的次级语言
1.C
2.Object - Oriented C++
3.Template C++
4.STL


2.尽量以const, enmu , inline 替换 #define(Prefer consts,enums,and inlines to #defines)


对于单纯常量,最好以const对象或enum替换#define
对于形似函数的宏,最好该有inline替换

使用#define的缺点:
1.记号名称并未进入记号表,被编译器当做常量替换处理,使得发生编译错误时不能追踪到#define所定义的名称。
2.会有各种宏问题,造成各种错误。
可以使用以下方法
使用const定义常量,可能比#define产生较小的程序大小。并解决问题1.

const double AspectRatio = 1.653;//常量第一个字母多为大写
const char* const Name_1 = "Queen";//将指针也声明为const
const std::string Name_2("Queen");//C++中使用string更好

class GamePlayer {
public:
    static const int NumTurns = 5;//class专属常量
    int scores[NumTurns];//使用class专属常量
};
//const int GamePlayer::NumTurns;//有些编译器需要在实现文件里提供定义

也可使用enum

class GamePlayer {
public:
    enum {
        NumTurns = 5
    };
    int scores[NumTurns];
};

使用inline代替宏

#define CALL_WITH_MAX(a,b) F( (a) > (b) ? (a) : (b) )//以较大者调用F
int a = 5, b = 0;
CALL_WITH_MAX(++a,b);
CALL_WITH_MAX(++a,b+10);

向上面这个宏,我们并不确定会不会调用++a两次,向此类的宏的缺点十分多,很不安全。使用inline代替。

template<typename T>
inline void callWithMax(const T& a, const T& b){
    f(a > b ? a : b);//以较大者调用f
}

3.尽可能使用const (Use const whenever possible)


将某些东西声明为const可帮助编译器侦测出错误的用法。const可被施加于任何作用域内的对象、函数参数、函数返回类型。成员函数本体。
编译器强制实施bitwise constness,但你编写程序时应该使用“概念上的常量性”。
当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复。

top-level const and low-level const

    int i = 0;
    int *const p1 = &i;//top-level const不能改变p1的值
    int ci = 1;
    const int *p2 = &ci;//low-level const不能通过p2改变ci的值
    int cj = 2;
    const int *const p3 = &cj;//不能改变p3的值也不能通过p3改变cj的值

迭代器中的const

    std::vector<int> vec;

    const std::vector<int>::iterator iter = vec.begin();//不能改变iter的值,即top-level const
    const auto it1 = vec.begin();//同上

    std::vector<int>::const_iterator cIter = vec.begin();//不能通过cIter改变vec.begin()的值,即low-level const
    auto it2 = vec.cbegin();//同上

使用const可限制一些错误的发生

class Rational {
public:
    Rational(int i):i(i){}
    const Rational operator+ (const Rational& rhs){
        return this->i + rhs.i;
    }
    int getI(){return i;}
private:
    int i;
};

    Rational a,b,c;
    (a + b) = c;//ERROR:No viable overloaded'='
    if (a + b = c)//ERROR:No viable overloaded'='
    //可避免对计算结果赋值,=与==的错误

const成员函数

class TextBlock{
public:
    TextBlock(std::string text):text(text){}
    const char& operator[](std::size_t position) const{
        return text[position];
    }
    char& operator[](std::size_t position){
        return text[position];
    }

private:
    std::string text;
};

int main(int argc, const char * argv[]) {
    TextBlock tb("Hello");
    std::cout<<tb[0];//H
    const TextBlock ctb("World");
    std::cout<<ctb[0];//W
    return 0;
}

在上例的const函数中

 const char& operator[](std::size_t position) const{
        return text[position];
    }

我们不能通过改函数修改成员变量,因为函数后的const限定了修改成员变量。因为编译器想要bitwise constness,但有时我们是需要逻辑上的const即logical constness。我们可以在变量声明时加上mutable关键字,可在const函数中修改该变量。
const 版本的operator[]和non-const版本的operator[]中需要一些重复的操作,例如边界检验等。我们可以在non-const函数中调用const函数解决代码重复问题。

const char& operator[](std::size_t position) const{
        //边界检验
        //检验数据完整性
        //.......
        return text[position];
    }
    char& operator[](std::size_t position){
        return
            const_cast<char&>(//移除const operator[]的const
                static_cast<const TextBlock&>(*this)//为this添加const
                [position]
                              );
    }

先用static_cast将*this转化为const类型以调用const版本的operator[],若不做次转化operator[]将无限调用自己。在用const_cast将const operator[]返回的内容去const。
不能在const版本的成员函数中调用non-const版本的成员函数,因为在non-const版本中可能会破坏其const性质。导致代码不安全。


4.确定对象被使用前已先被初始化


为内置型对象进行手工初始化,因为C++不保证初始化他们
构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在class中的声明次序相同。
为免除跨编译单元之初始化次序问题,请以local static对象替换non-local static对象

C++对定义于不同的编译单元内的non-local static对象的初始化相对次序并无明确定义。
假如用一个non-local static对象初始化另一个对象,用来初始化的non-local static对象可能并未初始化。造成程序错误。可以使用local static对象替换non-local static对象。

extern ClassA obj;
//修改为
ClassA& obj(){
    static ClassA obj;
    return obj;
}

使用obj()代替obj

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值