为什么对易失性 int 的常量引用需要static_cast

Why does a const reference to volatile int need a static_cast?

本文关键字:static cast 引用 常量 易失性 int 为什么      更新时间:2023-10-16

给定以下代码:

struct Foo { 
    volatile int i; 
};
const int& bar = foo.i; 

我得到:

error: invalid initialization of reference of type 'const int&' from expression of type 'volatile int'

除非我提供一个static_cast<volatile int>.

C++类型中的"波动性"的工作方式与"常量"几乎完全相同 - 也就是说,volatile的对象不能分配给非volatile引用,就像

const int i = 3;
int& j = i; // won't work

同样,只能在易失性对象上调用标记为 volatile 的方法:

struct S
{
    void do_something() volatile {}
    void do_something_else() {}
};
volatile S s;
s.do_something(); // fine
s.do_something_else(); // won't work

方法可以被"波动性"重载,就像它们可以被恒常性重载一样。

在C++标准中,这些东西被称为 cv 限定符,以强调它们以完全相同的方式工作。(C99 添加了第三个以相同方式工作的方式,restrict ,在某些C++编译器中可用作扩展)。您可以使用const_cast<>更改 cv 限定符 - 不需要更强大的static_cast<>

编辑:

为了清楚起见,一个类型可以同时具有 constvolatile 修饰符,总共有四种可能性:

int i;
const int j;
volatile int k;
const volatile int l;

const一样,volatile对象只能由volatile引用引用。否则,编译器无法知道通过引用访问对象需要是可变的。

volatile const int& bar = foo.i;
^^^^^^^^

除非我提供static_cast<volatile int>

通过添加强制转换来静默编译器错误很少是一个好主意。这不会给你一个对foo.i的引用,而是给你一个单独的副本。

如果你正在做一些非常奇怪的事情,需要对易失性对象的非易失性引用,你需要const_cast删除qualifer:

const int& weird = const_cast<int&>(foo.i);