条款 03:尽可能使用 const

条款 03:尽可能使用 const

Use const whenever possible

const 修饰指针和常量

char greeting[] = "Hello";
char* p = greeting;    // non-const pointer, non-const data
const char* p = greeting;    // non-const pointer, const data
char const * p = greeting;    // non-const pointer, const data
char* const p = greeting;    // const pointer, non-const data
const char* const p = greeting;    // const pointer, const data

const 修饰迭代器

std::vector<int> vec;

const std::vector<int>::iterator it = vec.begin();    // 效果等同 T* const
*it = 10;    // 可以改变成功
++it;    // 错误

std::vector<int>::const_iterator it = vec.begin();    // 效果等同 const T*
*it = 10;    // 错误
++it;    // 可以迭代成功

const 修饰函数返回值

class Rational {...};
const Rational operator* (const Rational& lhs, const Rational& rhs);

返回 const 能够避免下面这种错误

Rational a, b, c;
(a * b) = c;    // 错误,可能不是预期的

const 成员函数

  • 能够使 class 接口更加清晰,得知哪个函数会改动对象而哪个不会
  • 使 pass by reference-to-const 成为可能
const 重载

两个成员函数如果只是常量性不同,可以被重载

class TextBlock {
public:
    const char& operator[] (std::size_t) const { return text[position]; } // operator[] for const 对象
    char& operator[] (std::size_t) { return text[position]; } // operator[] for non-const 对象
private:
    std::string text;
};

TextBlock tb("Hello");
const TextBlock ctb("Hello");
tb[0] = 'x'; // 没问题
ctb[0] = 'x'; // 错误
bitwise constness 和 logical constness

主张 bitwise constness 的人认为,一旦成员函数被申明为 const,就不能改变任何成员变量(除 static),即不更改任意一个 bit。然后这种观念很容易出现不合理的地方,比如某个对象内包含一个指针,某个 const 成员函数未改变指针但是改变了指针所指的值,虽然符合 bitwise constness,但是导致了反直观效果。
主张 logical constness 的人认为,允许 const 成员函数改变某些 bits,但是应该不被客户端感知,或者说符合预期。如下面获取一个高速缓存的文本区块的长度,其中 textLength 和 lengthIsValid 会实时变更,且符合预期,则可以使用 mutable 关键字申明可变。

class CTextBlock {
public:
    std::size_t length() const;
private:
    char* pText;
    mutable std::size_t textLength;
    mutable bool lengthIsValid;
};

std::size_t CTextBlock::length const
{
    if (!lengthIsValid) {
        textLength = std::strlen(pText);
        lengthIsValid = true;
    }
    return textLength;
}
当实现等价时,重载时以 non-const 调用 const 避免重复

如果实现 const 和 non-const 两个版本的函数,代码会重复冗长,可以重载时以 non-const 调用 const 避免重复,反向则不行。

class CTextBlock {
public:
    const char& operator[] (std::size_t) const { return text[position]; }
    char& operator[] (std::size_t) {
        return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
    }
private:
    std::string text;
};

static_cast 将传入参数转为 const TextBlock&,const_cast 将返回值去 const。如果 non-const 版本实现中需要改变成员变量,则不适用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值