C++ 我说的对吗,const_cast之后修改一个绑定到临时变量的const的ref是可以的?

C++ 我说的对吗,const_cast之后修改一个绑定到临时变量的const的ref是可以的?,c++,reference,constants,const-cast,temporary-objects,C++,Reference,Constants,Const Cast,Temporary Objects,我想核实一下我对此事的理解和结论 在IRC上,有人问: 可以接受绑定到临时对象的const\u castaconst引用吗 翻译:他将一个ref to const绑定到一个临时变量上,他想抛弃它的常量来修改它 我的回答是,我以前问过,人们的共识似乎是,临时变量本身并不是天生的常量,因此,你可以摆脱对它们的引用的常量,并通过结果修改它们。而且,只要对-const的原始引用仍然存在,这就不会影响临时对象的生存期 即: int main() { const int& x = int(3

我想核实一下我对此事的理解和结论


在IRC上,有人问:

可以接受绑定到临时对象的
const\u cast
a
const
引用吗

翻译:他将一个ref to const绑定到一个临时变量上,他想抛弃它的
常量来修改它

我的回答是,我以前问过,人们的共识似乎是,临时变量本身并不是天生的
常量,因此,你可以摆脱对它们的引用的
常量,并通过结果修改它们。而且,只要对-
const
的原始引用仍然存在,这就不会影响临时对象的生存期

即:

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

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

   cout << x;
}
// Output: 4
// ^ Legal and safe
intmain()
{
常数int&x=int(3);
int&y=常数(x);
y=4;
cout否。

首先,据我所知,它是否是字面意思是 无关。非类类型的R值始终具有非cv限定值 类型(§3.10/9),但在§8.5.3(参考文件的初始化)中,我们 拥有:

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

[……]

--

否则,将使用非引用副本初始化规则(8.5)从初始值设定项表达式创建并初始化类型为“cv1 T1”的临时值。然后将引用绑定到临时值。如果T1与T2相关,则cv1必须与cv1相同或更大 除此之外,cv2;否则,程序的格式不正确

(前面的所有要点都涉及左值或类类型。)

就我们而言,我们有:

int const& x = ...;
因此CV1T1是
int const
,我们创建的临时对象具有
int const
。这是一个顶级常量(在对象上),因此任何尝试 修改它是未定义的行为


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

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

如果您自己显式地将临时对象创建为非常量类型的对象,并且情况保证常量引用专门附加到您创建的临时对象,那么您可以安全地放弃引用的常量并修改对象

另一方面,如果临时文件是由编译器隐式为您创建的,那么临时文件本身将是常量。在这种情况下,修改临时文件将导致UB

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


所以,在一般情况下,答案是否定的,而特定于实现的答案可能不同。

@Mark:哦,文字可能是一个错误的选择。我现在已经将这个问题改为非文字。我正要说,代码中没有临时性。幸运的是,我在做之前刷新了页面:)好的(但我在国家公园里找不到)上面写着“当它被宣布为康斯特时,你就不能抛弃康斯特尼斯”…所以问题是,一个文字是否声明为常量?我不这么认为,因为它会导致一个临时对象,那么它是否声明为常量?我不知道,但我的直觉是:no@MarkB:虽然
2.14.2
实际上并不像
2.14.5/12
对字符串文本那样禁止或取消对整数文本的修改。好奇s!相关,但不是重复:这难道不只是使3.10/9和8.5.3相互矛盾吗?@TomalakGeret'kal不是真的。§3.10/9讨论右值和左值。类似于
3
int(3)的表达式
是一个右值。§8.5.3讨论了如何初始化引用;引用从来都不是右值,必须引用对象。因此§8.5.3说编译器创建了一个临时对象,用右值初始化,并将引用绑定到该对象。您不会得到对整数文本的引用,因为这样的东西不存在;您会得到一个引用一个不可见的未命名对象,它具有引用类型(而不是初始值设定项)。我在@James的评论中发现的最有趣的事情是:你得到一个对一个不可见的未命名对象的引用,它具有引用类型(而不是初始值设定项)。太棒了。在这之后,一切都非常简单明了!@Nawaz当我阅读标准时,临时对象的类型仍然是
int const
。返回值是非类类型的右值(因此cv限定符被忽略---没有
int const f()
)。因此我们讨论了§8.5.3中的最后一点(在别处引用)。这里的要点是,非类类型的处理方式不同于类类型,而对于非类类型,临时类型具有引用类型(“cv1 T1”)。@DonalFellows在原始Fortran中,是的。类似于
f(3)
实际上可以调用值为4的
f
。“Standard”Fortran每次都要求生成的代码重新初始化参数,以便
f(3)
确实总是用3调用
f
。我在8.5.3/5中找不到任何东西表明RHS上的任何临时文件都不会符合James引用的条款。你能证明当我“显式地创建临时文件[我自己]”时,情况是不同的吗?@Tomalak Geret'kal:嗯,对于类类型<