簡體   English   中英

“auto&& a= f();”中的 a 的生命周期是多少其中 f() 按值返回 object?

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

問題是,

  1. 1A在這里是什么意思? (linux 盒子上的 GCC)
  2. auto &&應該是轉發引用,在這種情況下,由於f()按值返回A object ,因此應該將a推導出為右值引用,對嗎?
  3. 如果a確實是右值引用,並且由於(臨時)右值的生命周期只能通過 const 左值引用來延長, a go 應該在此行之后從 scope 中取出,對嗎?

編輯:正如許多人指出的那樣,修復了最后一個cout語句中最令人煩惱的問題。

優秀答案的總結,供后人參考:

  1. 1A是類型A的內部表示,由 Guillaume Racicot 編寫。 F1AvE表示 Function 樣式轉換為 typeid(A()) 導致 prvalue,作者 Ted Lyngmo。
  2. 事實證明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
  1. Richard Critten 給出的鏈接顯示“臨時 object 的生命周期可以通過綁定到 const 左值引用或右值引用(自 C++11 起)來擴展......”

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;
}
  1. lAA的內部名稱,“如果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 是值初始化的。

  2. 是的,如此處所示:

     static_assert(std::is_rvalue_reference_v<decltype(a)>); // like this, ... static_assert(std::is_same_v<decltype(a), A&&>); // or like this
  3. 它的生命周期不會在完整表達式的末尾結束,而是在封閉塊的末尾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM