[英]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.