这段代码是否有未定义行为(UB)?
struct A
{
void nonconst() {}
};
const A& a = A{};
const_cast<A&>(a).nonconst();
换句话说,这个(临时的)对象最初是const
吗?我查了标准但没找到答案,所以希望引用相关部分。
编辑: 对于那些说 A{}
不是 const
的人,那么你能进行 A{}.nonconst()
吗?
这段代码是否有未定义行为(UB)?
struct A
{
void nonconst() {}
};
const A& a = A{};
const_cast<A&>(a).nonconst();
换句话说,这个(临时的)对象最初是const
吗?我查了标准但没找到答案,所以希望引用相关部分。
编辑: 对于那些说 A{}
不是 const
的人,那么你能进行 A{}.nonconst()
吗?
a
的初始化如下:A{}
的类型被调整为const A
。prvalue
类型相同:const A
。const_cast<A&>(a).nonconst();
是未定义的行为。临时变量的类型与您声明的类型相同。
不幸的是,正如Oliv在他们的答案中指出的那样,引用初始化规则会将类型转换为匹配引用类型的类型,因此在这种情况下,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&&) = delete;
foo(c_bar{});
的编译。
A{}
创建的临时对象本身并不是 const。您只是创建了一个 const 引用,并将其强制转换为非 const,然后访问该临时对象。这并不会改变临时对象本身的 const 属性。如果您确定指针/引用所指向的对象实际上不是 const,则从指针/引用中强制转换 const 属性并不会导致未定义行为。如果对象实际上是 const,例如const A a; const A &ref = a; const_cast<A&>(ref).nonconst();
,那么这样做就会导致未定义行为。 - Remy LebeauA&&
。 - Jarod42