19

我想检查一下我对此事的理解和结论。


在 IRC 上,有人问:

绑定到临时对象const_cast的引用是否可以接受?const

翻译:他有一个 ref-to-const 绑定到一个临时的,他想抛弃它的const-ness 来修改它。

我的回答是我之前问过一个类似的问题,其中的共识似乎是临时工本身并不是天生const的,因此您可以摆脱const对他们的引用的-ness,并通过结果修改它们. 而且,只要那个原始的 ref-to-const仍然存在,这不会影响临时的生命周期。

那是:

int main()
{
   const int& x = int(3);

   int& y = const_cast<int&>(x);
   y = 4;

   cout << x;
}
// Output: 4
// ^ Legal and safe

我对吗?


(当然,这样的代码是否真的可取完全是另一回事!)

4

2 回答 2

9

不。

首先,据我所知,它是否是文字无关紧要。非类类型的右值始终具有非 cv 限定类型(第 3.10/9 节),但是,在第 8.5.3 节(引用的初始化)中,我们有:

对“cv1 T1”类型的引用由“cv2 T2”类型的表达式初始化,如下所示:

[...]

--

否则,将使用非引用复制初始化 (8.5) 的规则从初始化表达式创建并初始化“cv1 T1”类型的临时变量。然后将引用绑定到临时文件。如果 T1 与 T2 相关,则 cv1 必须与 cv2 具有相同的 cv-qualification 或大于 cv2 的 cvqualification;否则,程序格式错误。

(以上所有观点都涉及左值或类类型。)

在我们的例子中,我们有:

int const& x = ...;

所以cv1 T1int const,我们创建的临时对象有 type int const。这是一个顶级 const(在对象上),因此任何修改它的尝试都是未定义的行为。

至少,这是我的解释。我希望标准对此更清楚一点。

于 2011-11-23T17:41:29.447 回答
1

答案取决于临时的创建方式和引用的初始化方式。

如果您自己明确地将临时对象创建为非 const 类型的对象,并且这种情况保证 const 引用专门附加到您创建的临时对象,那么您可以安全地丢弃引用的 const 性并修改对象。

另一方面,如果编译器为您隐式创建临时变量,则临时变量本身将是 const。在这种情况下,修改该临时文件会导致 UB。

不幸的是,C++ 语言标准本身似乎并不能保证必须采用第一种初始化方法的任何情况。在任何情况下,编译器都可以引入原始临时文件的额外临时副本。新的临时变量将是 const (如上所述),因此不可修改。这是否发生是实现定义的,如 8.5.3/5 中所述。

因此,一般情况下答案是否定的,而特定于实现的答案可能会有所不同。

于 2011-11-23T18:25:47.643 回答