C++ 临时对象最初是常量吗?
这是密码吗C++ 临时对象最初是常量吗?,c++,constants,language-lawyer,undefined-behavior,temporary-objects,C++,Constants,Language Lawyer,Undefined Behavior,Temporary Objects,这是密码吗 struct A { void nonconst() {} }; const A& a = A{}; const_cast<A&>(a).nonconst(); 结构A { void nonst(){} }; 常数A&A=A{}; const_cast(a).nonst(); 换句话说,(临时)对象最初是const?我已经看过了标准,但找不到答案,所以希望能引用相关章节 Edit:对于那些说A{}不是const的人,那么你能做A{}.nonst()
struct A
{
void nonconst() {}
};
const A& a = A{};
const_cast<A&>(a).nonconst();
结构A
{
void nonst(){}
};
常数A&A=A{};
const_cast(a).nonst();
换句话说,(临时)对象最初是const
?我已经看过了标准,但找不到答案,所以希望能引用相关章节
Edit:对于那些说
A{}
不是const
的人,那么你能做A{}.nonst()
?临时文件的类型是你声明它的任何类型
不幸的是,正如引用初始化规则中指出的,转换类型以匹配引用类型,因此在本例中,a
实际上指的是const a
。它基本上在做
using const_A = const A;
const A& a = const_A{};
因为如果您想要阻止重载集接受您需要的常量PR值,您实际上可以创建常量PR值
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{});
}
需要实际停止
foo(c_bar{})代码>来自编译。临时文件的类型是您声明它的任何类型
不幸的是,正如引用初始化规则中指出的,转换类型以匹配引用类型,因此在本例中,a
实际上指的是const a
。它基本上在做
using const_A = const A;
const A& a = const_A{};
因为如果您想要阻止重载集接受您需要的常量PR值,您实际上可以创建常量PR值
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{});
}
需要实际停止foo(c_bar{})代码>来自编译。参考a
的初始化由(粗体)给出:
否则,如果初始值设定项表达式
- 是一个右值(但不是位字段)[……]
然后,第一种情况下初始值设定项表达式的值和第二种情况下的转换结果称为转换后的初始值设定项。
如果转换的初始值设定项是prvalue,则将其类型T4调整为类型“cv1 T4”([conv.qual])并应用临时物化转换([conv.rval])
因此,这意味着初始化引用的类型prvalue表达式,A{}
,被调整为const A
然后说:
类型为T的prvalue可以转换为类型为T的xvalue。
此转换初始化T类型的临时对象([class.temporary])
因此,绑定到引用的临时对象的类型与调整后的prvalue
type:const A
相同
所以代码const_cast(a).nonst()代码>是未定义的行为。引用a
的初始化由(粗体)给出:
否则,如果初始值设定项表达式
- 是一个右值(但不是位字段)[……]
然后,第一种情况下初始值设定项表达式的值和第二种情况下的转换结果称为转换后的初始值设定项。
如果转换的初始值设定项是prvalue,则将其类型T4调整为类型“cv1 T4”([conv.qual])并应用临时物化转换([conv.rval])
因此,这意味着初始化引用的类型prvalue表达式,A{}
,被调整为const A
然后说:
类型为T的prvalue可以转换为类型为T的xvalue。
此转换初始化T类型的临时对象([class.temporary])
因此,绑定到引用的临时对象的类型与调整后的prvalue
type:const A
相同
所以代码const_cast(a).nonst()代码>是未定义的行为。由{}
创建的临时本身不是常量。您只需创建一个对它的常量引用,然后丢弃该常量,然后访问临时变量。这不会改变临时文件本身的常量。如果您确信被指向/引用的对象实际上不是常量,那么就不能从指针/引用中去掉常量。如果对象实际上是常量,则为UB,例如常量A;常数A&ref=A;const_cast(参考)。nonconst()
您甚至可以将它绑定到A&&
。我不认为它真正被称为临时的,因为在这种情况下常量引用会延长生命周期。作为对您的编辑的响应,@RemyLebeau由A{}
创建的临时本身不是常量。在C++17中,A{}
甚至不创建临时对象。您只需创建一个对它的常量引用,然后丢弃该常量,然后访问临时变量。这不会改变临时文件本身的常量。如果您确信被指向/引用的对象实际上不是常量,那么就不能从指针/引用中去掉常量。如果对象实际上是常量,则为UB,例如常量A;常数A&ref=A;const_cast(参考)。nonconst()
您甚至可以将它绑定到A&&
。我不认为它真正被称为临时的,因为在这种情况下常量引用会延长生命周期。作为对您的编辑的响应,@RemyLebeau由A{}
创建的临时本身不是常量。在C++17中,A{}
甚至不创建临时对象;是未定义的行为,我认为UB是修改常量对象。这里没有修改。@LanguageLawyer True我想上面的代码是一个示例,而不是生产代码。所以我不认为非标准的主体是有意义的