条款03:尽可能的使用const关键字

一、先写写const的用法

const的位置 含义
const int a = 2; a的值不能被修改
const int *p = &a; p不会被修改,即p这个指针不会指向其他地方了
int* const p = &a; p这个指针指向的值不可以更改
const int* const p = &a; p这个指针指向的值和自己都不能发生更改。

修饰类成员的const方法

const还可以放在类方法后边,表示此函数承诺不修改类成员变量的值,比如:

class B {
    int num;
    void show() const {
        std::cout << num << std::endl;
    }
};

编译器会执行一种被称为bitwise的检查,检查是否存在修改内部值的情况。至于到了我们真正使用的情况下,我们可能不会遵循这个bitwise的检查方式。

比如,如果我们在类的成员中增加了一个作为缓存的变量值,比如:

class B {
    vector<int> nums;
    int numLen;
    bool numLenValid;

    int getLen() const {
        if (numLenValid) {
            return numLen;
        }
        numLen = nums.size();
        numLenValid = numLen;
        return numLen;
    }
};

这里好像有点咸鱼,但是假如我们把nums.size()替换成一个很费事的操作,那么这个缓存变量就体现出了它的价值了。

明显getLen()从语义上讲是不会修改类内的元素的值的,因为我们直接写成return nums.size()当然也是OK的,但是在这样的场景下它又确实修改了类内元素的值。此时我们可以使用mutable关键字。

class B {
    vector<int> nums;
    mutable int numLen;
    mutable bool numLenValid;
    int getLen() const {
        if (numLenValid) {
            return numLen;
        }
        numLen = nums.size();
        numLenValid = numLen;
        return numLen;
    }
};

此时的编译就没有问题了。

使用non-const调用const以完成代码复用

两个函数的cosnt修饰不同时,他们已经是两个不同的函数了。如果我们想要两个只有const修饰不同的函数之间共享大部分相同的代码时,需要用non-const的函数调用const的函数,而不是反过来。

因为我们已经承诺在const函数里不修改内部的值,所以使用const调用一个没有任何承诺的non-const是一种不好的行为。而反过来则没有任何顾虑。

class TextBlock{
publicconst chars operator[] (std::size_t position) const
    // 一如既往 
    { 
        return text[position];
    }

    char&operator[](std::size_t position) 
    //现在只调用const op[]
    {
        return const_cast<char&>( 
           //将op[]返回值的const转除
           static cast<const TextBlock>(*this) 
                //为*this加上const
                [position] //调用const op[]
            );
    }
};

results matching ""

    No results matching ""