[英]What is expected lifetime of std::intializer_list object in C++14?
請考慮這個簡化的c++14程序:
#include <iostream>
struct A
{
A() { std::cout << "A() "; }
~A() { std::cout << "~A() "; }
};
int main()
{
auto l = std::initializer_list<A>{A()};
std::cout << ". ";
}
https://gcc.godbolt.org/z/1GWvGfxne
GCC在這里打印
A() . ~A()
這意味着std::initializer_list
在范圍結束時被破壞。
叮當印:
A() ~A() .
在構造它的行中銷毀std::initializer_list
。
兩個編譯器都在這里正確運行還是其中一個是錯誤的?
這是微妙的。
std::initializer_list
由底層數組(由編譯器生成)支持。 這個數組就像一個臨時對象,而std::initializer_list
是一種綁定到它的引用類型。 因此,只要“引用”存在,它就會延長臨時數組的生命周期。
在 C++14 中,我們不保證復制省略。 所以應該發生的事情就像std::initializer_list<A>{A()}
產生了一個臨時的initializer_list
,綁定了另一個臨時數組,並將臨時的initializer_list
復制到l
。
就生命周期延長而言, std::initializer_list
行為類似於常規引用。 只有原始引用會延長生命周期,而我們的原始引用本身是臨時的。 因此,在包含l
初始化的完整表達式的末尾,底層數組不存在。 Clang 是正確的。
直接初始化...
std::initializer_list<A> l {A()};
...在兩個編譯器上產生相同的輸出。
同時,在為 C++17 編譯時,您的原始代碼在 GCC 和 Clang 上的行為相同。
根據cppreference :
在 CWG 問題 1696 解決之前,允許臨時對象綁定到構造函數初始值設定項列表中的引用成員,並且它僅持續到構造函數退出,而不是只要對象存在。 自 CWG 1696 以來,這種初始化的格式不正確,盡管許多編譯器仍然支持它(一個值得注意的例外是 clang)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.