[英]What is the life time of a in "auto&& a= f();" where f() returns an object by value?
#include <iostream>
#include <typeinfo>
class A {};
A f() { return A(); }
int main() {
auto &&a = f();
std::cout << typeid(f()).name() << std::endl;
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(A{}).name() << std::endl;
return 0;
}
它输出
1A
1A
1A
问题是,
1A
在这里是什么意思? (linux 盒子上的 GCC)auto &&
应该是转发引用,在这种情况下,由于f()
按值返回A
object ,因此应该将a
推导出为右值引用,对吗?a
确实是右值引用,并且由于(临时)右值的生命周期只能通过 const 左值引用来延长, a
go 应该在此行之后从 scope 中取出,对吗? 编辑:正如许多人指出的那样,修复了最后一个cout
语句中最令人烦恼的问题。
优秀答案的总结,供后人参考:
1A
是类型A
的内部表示,由 Guillaume Racicot 编写。 F1AvE
表示 Function 样式转换为 typeid(A()) 导致 prvalue,作者 Ted Lyngmo。typeid()
不是检查引用的工具,因为它提供了引用的结束类型。 Ted Lyngmo 给出了正确的方法,是的,它是一个 r 值参考。static_assert(std::is_rvalue_reference_v<decltype(a)>); // like this, ...
static_assert(std::is_same_v<decltype(a), A&&>); // or like this
1A
在这里是什么意思? (linux 盒子上的 GCC)
这意味着名称的长度是1
后跟字母。 关于如何修改类型有很多规则,但它会对其命名空间、模板参数值和其他内容进行编码。
auto &&
应该是转发引用,在这种情况下,由于 f() 按值返回 A object ,因此应该将 a 推导出为右值引用,对吗?
typeid
运算符丢弃所有顶级 cv 和 ref 限定符。
此外,它通过引用查看并返回所引用类型的类型信息。
从typeid 运算符页面:
如果 type 是引用类型,则结果引用表示引用类型的 std::type_info object。
但是,是的,推断的类型是A
,所以你声明A&&
。 但即使a
是一个右值引用,表达式a
也是一个左值。
如果 a 确实是右值引用,并且由于(临时)右值的生命周期只能通过 const 左值引用来延长,那么 go 应该在此行之后从 scope 中取出,对吗?
根据生命周期延长规则,scope 的生命周期结束。
现在解释为什么 typeid 不同。
这与右值或转发引用无关。 这是最令人头疼的解析问题。 A()
是返回A
且没有参数的 function。
使用{}
进行初始化,您会看到问题消失:
#include <iostream>
#include <typeinfo>
class A {};
A f() { return A(); }
int main() {
auto &&a = f();
std::cout << typeid(f()).name() << std::endl; // 1A
std::cout << typeid(a).name() << std::endl; // 1A
std::cout << typeid(A{}).name() << std::endl; // 1A
return 0;
}
lA
是A
的内部名称,“如果type是引用类型,则结果引用代表被引用类型的std::type_info
object。 ” - 并且a
是引用类型。
F1AvE
表示在typeid(A())
中的 Function 样式转换导致prvalue 。 您可以与更熟悉的东西进行比较,例如int()
,其中typeid::name()
从lA
更改为i
:
std::cout << typeid(int()).name() << std::endl; // FivE std::cout << typeid(A()).name() << std::endl; // F1AvE std::cout << typeid(int{}).name() << std::endl; // i std::cout << typeid(A{}).name() << std::endl; // 1A
显式new_type ( )
:
如果new_type命名一个非数组完整的 object 类型,则此表达式是new_type类型的纯右值,指定一个临时的(C++17 前) /其结果 object 是(可能添加了 cv 限定符)(C++17 起)那种类型的。 如果new_type是 object 类型,则 object 是值初始化的。
是的,如此处所示:
static_assert(std::is_rvalue_reference_v<decltype(a)>); // like this, ... static_assert(std::is_same_v<decltype(a), A&&>); // or like this
它的生命周期不会在完整表达式的末尾结束,而是在封闭块的末尾。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.