临时对象最初是常量吗

Is temporary object originally const?

本文关键字:常量 临时对象      更新时间:2023-10-16

这是UB代码吗?

struct A
{
void nonconst() {}
};
const A& a = A{};
const_cast<A&>(a).nonconst();

换句话说,(临时)对象最初是const吗?我看过标准,但找不到答案,所以希望能引用相关章节。

编辑:对于那些说A{}不是const的人,你能做A{}.nonconst()吗?

参考a的初始化由[dcl.init.ref]/5(bold mine):给出

否则,如果初始值设定项表达式

  • 是一个右值(但不是位字段)[…]

则第一种情况下初始值设定项表达式的值和第二种情况下转换的结果称为转换后的初始值设定值。如果转换后的初始值设定项是prvalue,则其类型T4将调整为类型"cv1T4"([conv.qual]),并应用临时物化转换([conw.rval])。

因此,这意味着初始化引用的类型prvalue表达式A{}被调整为const A

然后[conv.rval]状态:

T类型的prvalue可以转换为T类型的xvalue。此转换初始化T类型的临时对象([class.temporary])。

因此,绑定到引用的临时对象的类型与调整后的prvalue类型相同:const A

因此,代码const_cast<A&>(a).nonconst();未定义的行为

临时的类型是用什么类型声明它。

不幸的是,正如Oliv在他们的答案中指出的那样,引用初始化规则将类型转换为与引用类型匹配,因此在这种情况下,a实际上指的是const A。它基本上是在做

using const_A = const A;
const A& a = const_A{};

因为如果你想阻止过载集接受常量prvalue,你实际上可以创建常量prvalues,所以你需要有

ret_type function_name(some_type const&&) = delete;

否则,如果你有

ret_type function_name(some_type const&)

在重载设置中,如果您只删除,则常量prvalue将绑定到该值

ret_type function_name(some_type&&)

相反。你可以在中看到这一点

struct bar{};
void foo(bar const&) { std::cout << "void foo(bar const&)n"; }
void foo(bar&&) =delete;
using c_bar = const bar;
int main()
{   
foo(c_bar{});
}

这里,调用void foo(bar const&)是因为c_bar{}实际上是const,而不是在使用foo(bar{});时得到已删除的函数错误。添加

void foo(bar const&&) = delete;

需要实际停止CCD_ 17的编译。