为什么这个initializer_list在传递字符串时会出现异常?

时间:2011-04-09 13:41:32

标签: 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(); it != ite; ++it)
    std::cout << *it << std::endl;
}

我不知道我做错了什么。有人可以帮帮我吗?

2 个答案:

答案 0 :(得分:3)

看起来您在上面的示例中创建了两个初始化列表。临时{"hello", "stackoverflow"}std::initializer_list<std::string> a

在gcc上,{}初始化列表实际上是临时数组,其生命周期在完整语句之后结束(除非直接绑定到std::initializer_list,如下例中的注释行)。

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

当你开始循环时,你正在读无效的记忆。

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

#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;
}

使用gcc 4.5.0,我得到了

dtor
dtor
after a's construction

答案 1 :(得分:1)

std::initializer_list<std::string> a({"hello", "stackoverflow"});

如果我将其声明为:

std::initializer_list<std::string> a{"hello", "stackoverflow"}; //without ()

然后它正在运作:http://ideone.com/21mvL

但这很奇怪。看起来像是一个编译器错误。


编辑:

它肯定是编译器错误,因为如果我写(*it).c_str()它会打印字符串!!

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;

代码:http://ideone.com/hXr7V