【问题标题】:Why does this initializer_list use misbehave when passing strings?为什么这个 initializer_list 在传递字符串时会使用不当行为?
【发布时间】:2011-08-02 02:23:40
【问题描述】:

我已经尝试了我的 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;
}

我不知道我做错了什么。谁能帮帮我?

【问题讨论】:

    标签: c++ c++11 iterator stdinitializerlist


    【解决方案1】:

    看起来您在上面的示例中创建了两个初始值设定项列表。临时{"hello", "stackoverflow"}std::initializer_list&lt;std::string&gt; 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
    

    【讨论】:

      【解决方案2】:
      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

      【讨论】:

      • @Johannes:如果你删除c_str(),它不会打印"hello"ideone.com/NTRUh ...我很困惑。它有什么问题?
      • 这是因为您正在使用对局部变量的引用(当函数返回时,它超出了范围)。当您使用 c_str() 时,您只是幸运(或不幸,取决于观点)内存仍然包含对 char* 字符串的引用并且堆区域尚未被覆盖。 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多