ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ mutable与常对象语义详解

2022-07-24 19:03:46  阅读:149  来源: 互联网

标签:const constness 成员 C++ 详解 bitwise mutable 函数


摘编自 《Effective C++》 条款三。

“成员函数如果是const” 或者 “一个对象是const对象”到底意味什么?有两个流行概念:bitwise constness(又称physical constness)和 logical constness。

bitwise constness

bitwise const 阵营的人相信,成员函数只有在不更改对象之任何成员变量( static 除外)时才可以说是const。也就是说它不更改对象内的任何一个 bit。这种论点的好处是很容易侦测违反点: 编译器只需寻找成员变量的赋值动作即可。bitwise constness 正是C++对常量性( constness )的原始定义,因此const成员函数不可以更改对象内任何 non-static 成员变量。

不幸的是许多成员函数虽然不十足具备 const 性质却能通过 bitwise 测试。更具体地说,-一个更改了“指针所指物”的成员函数虽然不能算是 const,但如果只有指针(而非其所指物)隶属于对象,那么称此函数为 bitwise const 不会引发编译器异议。这导致反直观结果。假设我们有一个 CTextBlock class,用来封装C风格字符串,它将数据存储为 char* 而不是 string:

class CTextBlock {
public:
    ...
    char& operator[](std: :size_t position) const
    { return pText [position]; }

private:
    char* pText;
};

这个 class 不适当地将其 operator[] 声明为const成员函数,而该函数却返回一个reference指向对象内部值。假设暂时不管这个事实,请注意,operator[] 实现代码并不更改pText。于是编译器很开心地为operator[]产出目标码。它是 bitwise const,所有编译器都这么认定。但是看看它允许发生什么事:

const CTextBlock cctb ( "Hello");1/声明一个常量对象。char* pe = &cctb[0];
//调用const operator[]取得一个指针,//指向cctb的数据。
*pc = 'J';
// cctb现在有了"Jello”这样的内容。

这其中当然不该有任何错误:你创建一个常量对象并设以某值,而且只对它调用const成员函数。但你终究还是改变了它的值。这样一来,bitwise const 好像就失去了意义。

这种情况导出所谓的 logical constness。这一派拥护者主张,一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。例如你的CTextBlock class有可能高速缓存(cache)文本区块的长度以便应付询问:

logical constness

这种情况导出所谓的 logical constness。这一派拥护者主张,一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才得如此。例如你的CTextBlock class需要回答字符串长度,当然不可能现数,要添加一个变量缓存当前长度。

class CTextB1ock {
public:
    ...
    std::size_t length() const {
        if (!lengthIsvalid){
            textLength = std::strlen (pText); //错误!在const成员函数内能赋值给textLength
            lengthIsvalid = true; //也不能赋值给lengthIsValid。
        }
        return textLength;
    }
private:
    char* pText;
    std::size_t textLength; //最近一次计算的文本区块长度。
    bool lengthIsvalid; //目前的长度是否有效。
};

length 的实现当然不是 bitwise const,因为textLength和 lengthIsValid都可能被修改。这两笔数据被修改对const CTextBlock对象而言虽然可接受,但编译器不同意。它们坚持bitwise constness。怎么办?

mutable

解决办法很简单:利用C++的一个与const相关的摆动场:mutable(可变的)。mutable释放掉non-static成员变量的bitwise constness 约束:

...
private:
    char* pText;
    mutable std::size_t textLength; //最近一次计算的文本区块长度。
    mutable bool lengthIsvalid; //目前的长度是否有效。
};

从 “bitness” 来看,这个 const 函数不再是“常函数”了。但是从 “logical” 来看,我们觉得length显然没有修改字符串,那两个mutable变量只是辅助而已,修改他们不算破坏规则。

所以,有了 mutable,我们就可以定制自己的 “logical constness”,可以写明白在一个常量或者常函数里,哪些是可以改的,哪些是不能改的。

标签:const,constness,成员,C++,详解,bitwise,mutable,函数
来源: https://www.cnblogs.com/ofnoname/p/16515191.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有