【发布时间】:2013-07-22 14:23:30
【问题描述】:
我是一名嵌入式 C 开发人员,最近开始在嵌入式设备上处理 C++ 代码,我不确定当类访问易失性数据(例如内存映射寄存器或外部设备上的数据)时如何应用 const 正确性,例如模数转换器 (ADC)。
例如,我有一些类通过指针访问设备的内存映射寄存器来连接设备的硬件模块,如下所示:
class IOPin
{
public:
/* Constructor, destructor, other methods...*/
// should this be a const method?
bool ReadIOState() {return portregs_->state;}
private:
/* Other private stuff...*/
// Constructor points this to the right set of memory-mapped registers
volatile struct portregs_t
{
uint32_t control;
uint32_t state;
uint32_t someotherreg;
} *portregs_;
};
寄存器名称当然是为了举例而编造的。我正在为任何好奇的人使用 Microchip PIC32 设备。
根据我可能不正确的理解,标记方法const 意味着就调用者而言,对象的可观察状态不应改变。那么ReadIOState() 方法不是否应该是const,因为它访问的volatile 数据可能随时更改,因此调用者会观察到更改?还是应该是 const,因为 方法 没有明确改变任何东西?
目前,由于问题中所述的原因,我倾向于不使用该方法const。在偶然发现this GotW article 之后尤其如此,它指出const 的含义正在更改为“能够同时读取”。我的嵌入式应用程序是单线程的,但我想这可能是对constness 的一个很好的试金石。
另外,编译器如何处理const 方法?也就是说,当我想像这样轮询 IO 的状态时会发生什么:
// wait for IO pin to go high
while(!myIOpin.ReadIOState())
{}
如果ReadIOState() 是const,那么编译器是否可以重用一次调用后返回的值,或者它是否足够聪明地看到它正在访问volatile 数据而不这样做?
【问题讨论】:
-
我想知道你是否可以像创建 const 方法一样创建 volatile 方法。
-
void test() volatile {} 在 VS2012 上编译,但我不知道这是什么意思,因为我以前从未使用过 volatile。
-
@NeilKirk 是的,你可以做到。这意味着可以在
volatile实例上调用该函数。就像const函数可以在const实例上调用一样。如果您愿意,您甚至可以拥有成员函数的所有 4 个重载。 -
这些 cmets 让我意识到我必须考虑如何在中断例程中使用 C++ 对象。其中使用的变量通常被声明为 volatile,尽管我不确定这如何应用于我正在调用其方法而不是直接访问成员的对象。
标签: c++ embedded const-correctness