C ++大括号初始化列表,临时生命周期

时间:2014-07-05 12:24:55

标签: c++ c++11 initializer-list temporary-objects

我有以下代码:

string join(initializer_list<string_view> strings);

initializer_list是std :: initializer_list,string_view不是std :: string视图,但是与const string&amp;的构造函数非常相似的类。和const char *。

然后我调用了join

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

经过小规模调查后,我发现生成的初始值设定项列表的第一个元素不是"this",而是"\0his"。这是因为string("this")创建的临时的析构函数在创建临时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(...)

我希望在string("this")函数中提供join的内容。事实并非如此,因为`字符串(“this”)在之前被销毁了。

为什么在调用string("this")函数之前调用临时字符串join的析构函数,或者换句话说为什么string("this")的生命周期延长到完整的结尾?表达式join({ string("this") })

1 个答案:

答案 0 :(得分:0)

我认为可能在这里发生的是你正在从对字符串的引用构造你的initializer_list,以便在你的initializer_list完成构建时字符串超出范围。

您看到您的字符串不是join()函数的参数,而是您构造的initializer_list的参数。

我的猜测是构造了initializer_list,你的字符串超出了范围,然后你的join()函数尝试通过string_view中包含的引用访问死字符串。