条款03:尽可能多使用const

目录

1.const修饰指针

2.STL迭代器 

3.const修饰返回值

 4.const修饰成员函数

5.借助const成员函数,生成一个非const成员函数


1.const修饰指针

char greeting = "hello";
char * p = greeting // 指针本身和指向内容均可修改
const char * p = greeting // 指针本身可修改 指向内容不可修改
char *const p = greeting // 指针本身不可修改 指向内容可修改
const char *const p = greeting // 指针本身不可修改 指向内容不可修改

const 放在 * 号的左边是修饰指向的内容, 放在* 右边是修饰指针本身。

2.STL迭代器 

STL的迭代器就是以指针进行塑膜的,所以迭代的使用和指针非常相似。

非const类型的指针 对应 iterator, const 类型的指针对应 const_iterator.

std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin();
*iter = 10; // 没问题 因为是非const迭代器 指针指向的内容可以被修改
iter++; // 错误 因为迭代器本身被 const修饰不可修改

std::vector<int>::const_iterator citer = vec.begin();
*citer = 10; //错误 因为是const迭代器 迭代器指向的内容不可修改
*citer++; // 没问题 迭代器本身是非const

3.const修饰返回值

const修饰返回值,这个主要是防止对函数返回值进行修改。

正常来说是不会出现这个问题,毕竟哪个程序员会修改函数的返回值? 主要目的是还是防止因为疏忽,不小心对返回值进行修改。

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


Rational a, b;
if((a * b) = 0) // 防止这种情况的发生,程序员的本意是 ==

//当然你也可以这样写
if(0 == (a* b)) // 

这样在你 不小心携程 = 的时候 编译器就会及时的制止你。

 4.const修饰成员函数

class textBlock
{
public:
    char& operator[](const size_t &pos) //非const对象调用
    {
        return _str[pos];
    }

    const char& operator[](const size_t &pos) const // const对象调用
    {
        return _str[pos];
    }
private:
    std::string _str;
};

1.位常量性

这种说法主张的是const成员函数的任何一个比特位都是不可以修改。

注意:如果成员变量中含有指针,那么这个这个指针指向的内容是可被修改的。

class testBlock
{
public:
    char &operator[](size_t pos) const
     { return _str[pos]; }
private:
    char * _str;
}

const testBlock tb("hello"); 

char * p = &tb[0]; //调用char &operator[](size_t pos) const
*p = 'j'; 

 这段代码是没问题的,完全符合bitwise,

2.逻辑常量性

这种说法主张,在const成员函数中某些变量是可以被修改的,但这些修改一定是不可见。

当然这种做法需要借助 mutable关键字来释放,非静态成员变量的位常量性,是其支持逻辑常量性。

class CTextBlock {
public:
    int length() const {
        if (!lengthIsValid) {
            textLength = std::strlen(pText); // mutable成员可修改
            lengthIsValid = true;
        }
        return textLength;
    }
private:
    char* pText;
    mutable int textLength;    // 缓存计算结果
    mutable bool lengthIsValid; // 缓存有效性标志
};

5.借助const成员函数,生成一个非const成员函数

一个函数支持const和非const两种版本,那么函数一定会有代码重复的问题。

假设我想要支持两个版本的成员函数的代码量巨大。

class testBlock
{
public:
    const char &operator[](size_t pos) const
     { 
        //很多代码
        return _str[pos]; 
     }

    char &operator[](size_t pos)
    {
         return const_cast<char&>(static_cast<const testBlock&>(*this)[pos]);
    }
private:
    char * _str;
}

 1.将 *this 转化位为 const testBlock类型

2.调用    const char &operator[](size_t pos) const 

3.将const char &operator[](size_t pos) const 返回值的const 去掉。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值