此代码是UB吗?
struct A
{
void nonconst() {}
};
const A& a = A{};
const_cast<A&>(a).nonconst();
换句话说,(临时)对象最初是const
吗?我浏览了该标准,但找不到答案,因此希望引用相关部分。
编辑: :对于那些说A{}
不是const
的人,您可以做A{}.nonconst()
吗?
答案 0 :(得分:9)
引用a
的初始化由[dcl.init.ref]/5(粗体)给出:
否则,如果初始化表达式为
- 是右值(但不是位字段)[...]
然后,在第一种情况下的初始值设定项表达式的值,在第二种情况下的转换结果称为转换后的初始值设定项。 如果转换后的初始值设定项是prvalue,则将其类型T4调整为“ cv1 T4”([conv.qual]),并应用临时实现转换([conv.rval])。 >
因此,这意味着将初始化引用A{}
的类型prvalue表达式调整为const A
。
然后[conv.rval]声明:
类型T的prvalue可以转换为类型T的xvalue。 此转换将初始化类型T的临时对象([class.temporary])。
因此绑定到引用的临时对象的类型与调整后的prvalue
类型:const A
相同。
因此,代码const_cast<A&>(a).nonconst();
是未定义的行为。
答案 1 :(得分:3)
临时类型是您声明时使用的任何类型。
不幸的是,由于Oliv在their answer中指出,参考初始化规则将类型转换为与参考类型匹配,因此在这种情况下a
实际上是指const A
。基本上在做
using const_A = const A;
const A& a = const_A{};
因为如果您想停止过载集以接受需要的常量prvalue,则实际上可以创建常量prvalue。
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;
实际上需要停止foo(c_bar{});
的编译。