C++ 逻辑常数与物理常数的区别

C++ 逻辑常数与物理常数的区别,c++,C++,这两个术语之间的区别是什么?为什么我需要mutable?当对象中存在可被视为“内部”的字段时,您需要mutable,即该类的任何外部用户都无法确定这些字段的值。该类可能需要写入这些字段,即使实例被视为常量,即不更改 以硬盘驱动器为例;它的缓存就是这种状态的一个例子。当从实际磁盘读取数据时,缓存被写入 不可能在C++中清晰地表达,而不必让相应的成员可更改的< /代码>,即使在标记为“代码> const < />代码的方法中也允许更改它们。正如评论中所指出的,你总是可以伸手去拿锤子,用const_c

这两个术语之间的区别是什么?为什么我需要
mutable

当对象中存在可被视为“内部”的字段时,您需要
mutable
,即该类的任何外部用户都无法确定这些字段的值。该类可能需要写入这些字段,即使实例被视为常量,即不更改

以硬盘驱动器为例;它的缓存就是这种状态的一个例子。当从实际磁盘读取数据时,缓存被写入

不可能在C++中清晰地表达,而不必让相应的成员<代码>可更改的< /代码>,即使在标记为“代码> const < />代码的方法中也允许更改它们。正如评论中所指出的,你总是可以伸手去拿锤子,用

const_cast
来移除
const
-ness,但这当然是作弊

“物理”常量来自于声明一个对象
const
,原则上可以通过将对象放入只读内存来强制执行,因此它不能更改。试图改变它将导致未定义的行为;它可能会改变,也可能不会,或者可能会触发保护故障,或者可能会融化内存芯片

“逻辑”常量来自声明引用或指针
const
,由编译器强制执行。对象本身可能是也可能不是“物理”常量,但引用不能在没有强制转换的情况下用于修改它。如果对象不是“物理”const,那么C++允许你修改它,使用<代码> conistasCase<代码>来规避保护。 即使类对象本身(或用于访问它的引用或指针)是
const
,也可以修改
mutable
类成员。例如,在读取操作期间必须锁定的互斥锁,以及用于存储昂贵读取操作结果的缓存。在这两种情况下,操作本身应该是一个
const
函数(因为它不影响对象的可见状态),但它需要修改互斥锁或缓存,因此它们需要是
可变的。它也可以被滥用,使对象在逻辑上不应该发生变化的时候发生明显变化,因此小心使用它;如果成员不构成外部可见状态的一部分,则仅声明成员可更改。

Scott Meyers,第3项:

尽可能使用
const

在这个话题上有一个很好的讨论(有例子)。很难写出比斯科特更好的作品


还要注意,物理常量也称为位常量。

另一个这样的示例是由不同线程共享的对象中的互斥量。读取操作不会修改对象,但必须在此过程中获取并释放互斥体。互斥体成员对象在操作过程中会发生明显的变化,即使操作的结果不会改变对象本身。如果感知到的状态保持不变,即使内部元素发生变化,操作在对象上也是常量。你能给我一个小例子(代码)说明我可以用mutable做什么,不能用const做什么吗,这也显示了逻辑和物理一致性的不同,我在谷歌中找到了一些解释,但是找不到好的例子,因为缓存有点难以理解,这是不可能在C++中表达的,而不必让相应的成员<代码>易变的< /代码>。这种说法是不正确的,因为它可以通过铸造对象或成员的方式移除常量来实现(过去也是如此)。关键字
mutable
是在之后出现的,当时逻辑常量的概念已经实现,因为程序员正在手动删除对象的常量以获得这种效果,使其更易于维护和执行。请看。@Adrian谢谢,添加了一些关于
const\u cast
。这读起来很好:-),但非常错误:-(.“物理”constness来自于声明一个对象const“-
const
不能保证你的“物理constness”:成员仍然可以是
可变的
,并在运行时更改。由于这是允许的,编译器/链接器等默认情况下不会将此类对象放置在只读内存中,即使它们是
静态常量
。如果通过一些非标准的编译器/链接器/加载程序标志将它们强制放置在只读内存中,则程序员必须手动避免
>可变的
成员。对象和指针/引用之间的区别实际上是不相关的。@TonyDelroy-我把Mike关于“将对象放入只读内存”的回答作为一种修辞(并且修辞有效)声明来说明物理常数和逻辑常数之间的区别,而不是说编译器实际上会这样做;他也没有说编译器会这样做。此外,我不同意他对指针和引用的区分是无关的。答案在概念上是可靠和正确的。TonyDelroy在我看来,当他说答案“非常错误”时是不正确的。即使类本身(或用于访问它的引用或指针)是可变类成员,也可以修改它is const。类不是const。只有实例可以是const。从符号名称看,符号的类型描述了实例的const。否则这是一个很好的解释。@Adrian:是的,这就是我的意思。很抱歉措辞有点含糊不清。你很好地澄清了这个概念,因此+1。