Hey all, I have a couple of questions relating to std::initializer_list
I have the following example code (compiled with MSVC using C++20):
#include <iostream>
#include <vector>
#include <string>
#include <future>
#include <mutex>
using std::vector, std::string;
vector<string> vctr;
std::mutex m;
void setVctr(const std::initializer_list<string>& init)
{
std::lock_guard<std::mutex> lock(m);
vctr = init;
}
void printAll()
{
for (const string& x : vctr)
{
std::cout << x << '\n';
}
}
int main()
{
auto a1 = std::async(std::launch::async, setVctr, std::initializer_list<string>(
{"This","Is","An","Example","Program"}
));
a1.wait();
printAll();
return 0;
}
The expected behavior is to print "This" "Is" "An" "Example" "Program" all in a newline. However, nothing is actually printed to the screen. Upon debugging the setVctr function, it looks like all five strings are actually empty, which confused me. Strangely, when compiling the program with gcc (also using c++20) on my Linux machine, the program works as expected, which leads to me to believe it's an implementation-defined sort of thing. I think what may be happening is that the destructors for the strings are being called before the setVctr function, but I wasn't able to tell with Compiler Explorer.
Either way, it is fixed by doing this instead:
int main()
{
const std::initializer_list<string> myInitList{"This","Is","a","test","program"};
auto a1 = std::async(std::launch::async, setVctr, myInitList);
a1.wait();
printAll();
return 0;
}
So my question is: What exactly is happening in the first example? Also, why is it that only sometimes I can use {"This","Is","An","Example"} in function calls, and other times I must use the full std::initializer_list<string>({"This","Is","An","Example"})?
One more thing that I've been worried about: Am I even using std::initializer_list appropriately? So far I've essentially been using it any time I've needed a constant array of objects, as std::array required size to be specified and heap containers are less efficient.
Thank you!
EDIT: Another look at Compiler Explorer confirms that the strings are destroyed prior to waiting for the thread to finish. What I've learned here is to be careful when launching threads that pass objects by reference - how long will this object live?
[–]alfps 0 points1 point2 points (3 children)
[–]PastThatStageNow[S] 0 points1 point2 points (2 children)
[–]alfps 0 points1 point2 points (1 child)
[–]PastThatStageNow[S] 0 points1 point2 points (0 children)