簡體   English   中英

C ++括號初始化程序列表,臨時生存期

[英]C++ brace initializer list, temporary lifetime

我有以下代碼:

string join(initializer_list<string_view> strings);

initializer_list是std :: initializer_list,而string_view不是std :: string視圖,但與const string&和const char *的構造函數非常相似。

然后我得到了join以下調用:

EXPECT_EQ("this", join({ string("this") }));

經過"\\0his"調查,我發現結果初始化列表的第一個元素不是"this"而是"\\0his" 這是因為由string("this")創建的臨時string_view的析構函數在創建臨時string_view之后立即被調用(因此它包含無效的指針)。 為什么這樣做,以使string("this")的生存期不延長到完整表達式EXPECT_EQ("this", join({ string("this") }));

編輯

好的,正如您所建議的,有一個獨立的示例:

#include <iostream>
#include <string>

using namespace std;

class string_view {
public:
    string_view(const string& str)
        : _begin(str.data())
        , _end(str.data() + str.size()) {
    std::cout << "string_view(...)" << std::endl;
    }

    const char* _begin;
    const char* _end;
};

void join(initializer_list<string_view> strings) {
    std::cout << "join(...)" << std::endl;
    for (auto i = 0u; i < 5; ++i) {
        std::cout << int(strings.begin()->_begin[i]) << " " << strings.begin()->_begin[i] << std::endl;
    }
}

int main() {
    join({ string("this") });
    return 0;
}

該程序的輸出使用最后的Visual Studio C ++(Express)編譯:

string_view(...)
join(...)
0
104 h
105 i
115 s
0

由於上述程序的格式可能不正確,因此編譯器之間可能會有所不同。

我研究了調試器中調用的順序是什么,有以下順序:

main()
    basic_string(const char*)
    string_view(const string&)
    ~basic_string()
    initializer_list(...)
    join(...)

我希望在join函數中可以使用string("this")的內容。 事實並非如此,因為`string(“ this”)之前已被銷毀。

為什么在調用join函數之前調用了臨時字符串string("this")的析構函數,或者為什么string("this")的生命周期沒有擴展到完整表達式join({ string("this") })

我認為這里可能發生的事情是,您正在通過對字符串的引用來構造initializer_list,以便當initializer_list完成構造后,字符串超出范圍。

您會看到您的字符串不是join()函數的參數,而是您構造的initializer_list的參數。

我的猜測是構造了initializer_list,您的字符串超出范圍,然后您的join()函數嘗試通過string_view中包含的引用訪問死字符串。

暫無
暫無

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

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