首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【读书笔记】Effective C++ 条款3:尽可能使用const

【读书笔记】Effective C++ 条款3:尽可能使用const

作者头像
用户11952558
发布2026-01-09 14:13:58
发布2026-01-09 14:13:58
760
举报

1. const的本质:将编译器当作你的朋友去维护一个常量

2. 指针的const

代码语言:javascript
复制
const char *str1 = "hello";
str1 = "ttt";  // 可以改变指针指向

在上面的代码中,const仅仅为保证str1指向的字符不被改变,但是我们可以将str1指向的内容改变。

代码语言:javascript
复制
char str[] = "hello";
char* const str2 = str;
str2[0] = 'a';  // 可以修改内容

上面代码中的const只能维持str2指向不变,但是内容可以改变。

因此,我们要将两个const结合:

代码语言:javascript
复制
const char* const str3 = "hello";

尽可能保证常量不被改变。在这过程中,将const作为让编译器维护常量的口令,将编译器当作你的朋友。

但是这一方案也并非天衣无缝(远古版本c++),在下面会提到

3. 迭代器的const

由于迭代器是基于指针的,也就同理,意味着有两种类型的const:const iteratorconst_iterator

  • const iterator相当于char* constT* const),指向不可变
  • const_iterator相当于const char*const T*),内容不可变

4. 用const减少调用错误

代码语言:javascript
复制
class A
{
public:
    A(const int a = 1)
        :_a(a)
    { }
    
    A operator*(const A& aa)
    {
        A ret(_a * aa._a);
        return ret;
    }
    
    A operator=(const A& aa)
    {
        _a = aa._a;
        return *this;
    }
    
    bool operator==(const A& aa) const
    {
        return _a == aa._a;
    }
    
    operator bool()
    {
        return _a != 0;
    }
    
private:
    int _a;
};

A a(1);
A b(2);
A c(3);

在这样一个类中,如果误将if (b == c)写成if (b = c),那么你是不会察觉的。但如果加上const,那么就会报错。

5. const成员函数

在类的函数后加上const有两个作用:

  • 让函数做什么更加容易理解
  • 可以传const对象

6. bitewise观点

首先,假设有一座房子,坏没坏有种标准。bitewise观点就是只要房子外壳还是一样的,但是里面怎么坏都无所谓。这就是编译器对于const的理解:只要这块内存不动,至于内存怎么变无所谓。

这样就会发生神奇的事(远古版本c++):

代码语言:javascript
复制
const char* const str = "hello";
char* s = &str[0];
s[0] = 'a';
cout << str << endl;

(注意:由于书本是比较老的,现在即便是c++98编译也会报错,但是由于是书中的例子,就讲究看一下吧)

同时,对于缓存,我们可能需要微小改动里面的值,即使改变了也依旧认为是const。因此也有bitewise观点认为错误,但我们需要的情况。

7. 修正:mutable

在第六点,我们发现bitewise观点很多时候并不能完全胜任

因此就需要修正

有可能我们在const函数中也需要修改值,加上mutable就可以了。

代码语言:javascript
复制
class A
{
public:
    A(int a, int b)
        :_a(a)
        ,_b(b)
    { }
    
    int getb()
    {
        _b = 100;
        return _b;
    }
    
private:
    int _a;
    mutable int _b;
};

这就是logical constness观点。

8. Const和非const写法归一

比如[]的重载,const函数和非const函数绝大多数代码都是一样的,因此能否复用呢?可以用非const复用const。

代码语言:javascript
复制
namespace bit
{
class string
{
public:
    string(const char* str = "")
    {
        _size = strlen(str);
        _capacity = _size;
        _str = new char[_capacity + 1];
        strcpy(_str, str);
    }
    
    char& operator[](size_t pos)
    {
        assert(pos < _size);
        assert(pos);
        return _str[pos];
    }
    
    const char& operator[](size_t pos) const
    {
        assert(pos < _size);
        assert(pos);
        return _str[pos];
    }
    
    ~string()
    {
        if (_str)
        {
            delete[] _str;
            _str = nullptr;
            _size = 0;
            _capacity = 0;
        }
    }
    
private:
    char* _str = nullptr;
    size_t _capacity = 0;
    size_t _size = 0;
    static const size_t npos = -1;
};
}

上面是简易的string类。

char& operator[](size_t pos)改为以下代码:

代码语言:javascript
复制
char& operator[](size_t pos)
{
    return
        const_cast<char&>(
            static_cast<const bit::string&>(*this)
            [pos]
        );
}
详细解析
  1. static_cast<const bit::string&>(*this) 其中static_cast为c++的安全转换,将*this转为const bit::string的引用。
  2. [pos]调用[]重载,返回const char 调用const版本的operator[]。
  3. const_cast<char&> const_cast将常性去掉,转为char引用。

可以看到,代码繁琐冗长,因此要权衡代码可读性与简洁性。

可以const调用非const吗?

理论可以,但是调用非const就意味着需要冒着被改变的风险。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. const的本质:将编译器当作你的朋友去维护一个常量
  • 2. 指针的const
  • 3. 迭代器的const
  • 4. 用const减少调用错误
  • 5. const成员函数
  • 6. bitewise观点
  • 7. 修正:mutable
  • 8. Const和非const写法归一
    • 详细解析
    • 可以const调用非const吗?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档