5

假设我有以下成员函数:

void CFoo::regWrite( int addr, int data )
{
  reg_write( addr, data ); // driver call to e.g. write a firmware register
}

显然,调用此函数不会修改调用它的对象的内部状态。但是,它会更改此Foo实例所代表的任何内容的状态。

在这样的情况下,应该Foo::regWrite(int addr, int data)是一个 const 函数吗?

4

4 回答 4

3

您必须确定类的“逻辑上的 const”的含义是什么CFoo,这取决于该类的用途。

如果CFoo被解释为引用某些数据,那么能够通过 的const实例修改该数据可能是有意义的CFoo,在这种情况下,您的成员函数将是const. 例如,考虑引用某些数据的其他类型 - 您可以修改 achar *const或 a的引用const std::unique_ptr<char>

如果CFoo被解释为拥有一些数据const,那么禁止通过CFoo. 例如,考虑容器,其中元素在逻辑上是“对象状态的一部分”,即使它们在物理上不是对象的一部分。所以vector::operator[]有一个返回 aconst T&而不是 a的 const 重载T&insert成员函数是非常量的,等等。

于 2012-10-16T10:25:13.727 回答
1

如果您在类中有指向其他对象的指针,则会出现类似的问题:您的 const 方法然后可以调用其他对象的非 const 方法,从而修改它。

如果您将硬件视为您的类引用的其他对象,那么修改固件设置将是完全有效的(因为仅更改了“引用”对象)。如果您希望您的类“代表”硬件(或其中的一部分),我宁愿建议不要将该方法标记为const.

所以我认为这主要取决于你如何设计你的课程。

于 2012-10-16T10:25:29.590 回答
1

由程序员来定义“const”对类的含义。使用说明符mutable,您甚至可以拥有一个const在成员中更改值的对象。当涉及到硬件时,可能会将配置视为 const 正确性的目标:只要配置不改变,对象就可以被认为是常量。

于 2012-10-16T10:13:17.363 回答
1

有两种看待这一点的方法——优化角度,以及这个声明的逻辑。哪个更重要由您决定。

优化

编辑:我做了一些不正确的假设。似乎编译器实际上并不能自由地进行下面的优化,并且只会通过分析方法的主体来确保没有修改发生(即使这样也只是在简单的情况下)。

拥有这const将允许编译器进行更多优化。它知道regWrite不会更改对象中的任何字段,因此如果将它们存储在寄存器中,它可以保留它们,并进行类似的优化,依赖于对象字段不被更改。

当您进行这样的定义时,这确实是编译器唯一依赖的东西,因此拥有它const是可以的,并且理论上可以提供更好的性能。

合乎逻辑

const拥有一种其全部目的是破坏性改变的方法感觉不直观。程序员通常的直觉是,只要我只调用 const 方法,其他const方法的结果就不会改变。如果你违反了这个不成文的合同,预计人们会感到惊讶——即使编译器可以接受。

我不确定这是否会在这里被违反——这将取决于这个类中的其他代码。但是,如果没有其他重要的考虑因素(性能等),const(对我来说)主要是界面上的一个标记,上面写着“调用它不会改变这个对象的状态”,对于“状态”的广义定义。

然而,这是一个模糊的领域,你认为什么是状态变化取决于你。如果你认为你的固件对象代表一个到内部的链接,那么写一个寄存器不会改变这个链接的任何内容并且是 const 的。如果您认为它代表底层寄存器的状态,那么写入寄存器就是状态的变化。

于 2012-10-16T10:15:08.843 回答