C++ 为什么这个初始值设定项列表在传递字符串时会使用行为不当?

C++ 为什么这个初始值设定项列表在传递字符串时会使用行为不当?,c++,c++11,iterator,stdinitializerlist,C++,C++11,Iterator,Stdinitializerlist,我尝试了我的G++版本的C++0x初始值设定项列表实现,但它只输出空行 #include <initializer_list> #include <iostream> #include <string> int main() { std::initializer_list<std::string> a({"hello", "stackoverflow"}); for(auto it = a.begin(), ite = a.end();

我尝试了我的G++版本的C++0x初始值设定项列表实现,但它只输出空行

#include <initializer_list>
#include <iostream>
#include <string>

int main() {
  std::initializer_list<std::string> a({"hello", "stackoverflow"});
  for(auto it = a.begin(), ite = a.end(); it != ite; ++it)
    std::cout << *it << std::endl;
}
#包括
#包括
#包括
int main(){
std::初始值设定项\列表a({“hello”,“stackoverflow”});
对于(自动it=a.begin(),ite=a.end();it!=ite;++it)
标准::cout

代码:

在上面的示例中,您似乎正在创建两个初始值设定项列表。临时的{“hello”,“stackoverflow”}std::initializer\u列表a

在gcc上,
{}
初始值设定项列表实际上是临时数组,其生存期在完整语句后结束(除非直接绑定到
std::initializer\u list
类似下面示例中注释行中的内容)

第一个列表的内部数组的生存期在
a
的构造函数返回后立即结束,因此
a
的数组现在指向无效内存(gcc仅复制指针)。您可以检查
std::string
析构函数是否在进入循环之前被调用

当您进入循环时,您正在读取无效内存

根据最新标准草案(n3242),§18.9/1,初始值设定项列表甚至不能像那样复制(它们不提供带参数的构造函数)


@约翰内斯:如果删除
c_str()
,它不会打印
“hello”
:…我很困惑。它有什么问题?这是因为您使用的是局部变量引用(函数返回时它超出了范围)。当您使用c_str()时,您只是幸运(或者不幸运,取决于角度)内存仍然包含对
char*
字符串的引用,并且堆区域尚未被覆盖。:)
std::initializer_list<std::string> a({"hello", "stackoverflow"});
std::initializer_list<std::string> a{"hello", "stackoverflow"}; //without ()
std::initializer_list<std::string> a({"hello", "stackoverflow"}); //with ()
for(auto it = a.begin(), ite = a.end(); it != ite; ++it)
   std::cout << (*it).c_str() << std::endl;
#include <initializer_list>
#include <iostream>

class A
{
public:
  A(int)
  { }

  ~A()
  {
    std::cout << "dtor" << std::endl;
  }
};

int main()
{
  std::initializer_list<A> a({A(2), A(3)});
  // vs std::initializer_list<A> a{A(2), A(3)};
  std::cout << "after a's construction" << std::endl;
}
dtor
dtor
after a's construction