I have the following code:
string join(initializer_list<string_view> strings);
initializer_list is std :: initializer_list, and string_view is not a std :: string view, but a very similar class with constructors from const string & and const char *.
Then I have the following join call:
EXPECT_EQ("this", join({ string("this") }));
After a little research, I found that the first element of the resulting initializer list is not "this" , but "\0his" . This is because the destructor of the temporary created string("this") is called immediately after the creation of the temporary string_view (therefore, it contains invalid pointers). Why is it so that the lifetime of string("this") not extended to the end of the full expression EXPECT_EQ("this", join({ string("this") })); ?
Edit
Well, as you suggested, there is a self-sufficient example:
#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; }
The result of this program compiled with the latest Visual Studio C ++ (Express):
string_view(...) join(...) 0 104 h 105 i 115 s 0
It may differ from compiler to compiler, since the above program is probably poorly formed.
I investigated what the order of calls in the debugger is, and there is a sequence:
main() basic_string(const char*) string_view(const string&) ~basic_string() initializer_list(...) join(...)
I would like the contents of string("this") be available inside the join function. And this is not so, because `string (" this ") is destroyed earlier.
Why is the time line destructor string("this") called before the join function is called, or in other words, why is it not the lifetime of string("this") extended to the end of the complete join({ string("this") }) expression join({ string("this") }) ?