2011-04-09 70 views
9

我试过我的G ++版本的C++ 0x初始化列表实现,但它只输出空行。为什么initializer_list在传递字符串时使用不当?

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

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

回答

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

+4

这将打印字符串' “你好”'太:http://ideone.com/C9Q7p -.- – 2011-04-09 14:51:10

+0

@Johannes:如果您删除'c_str()',它不会打印'“你好”':http://ideone.com/NTRUh ...我很困惑。它有什么问题? – Nawaz 2011-04-09 14:57:58

+1

这是因为你正在引用局部变量(当函数返回时超出了范围)。当你使用c_str()时,你只是幸运的(或者不幸的,取决于观点),内存仍然包含对char *字符串的引用,并且堆区还没有被覆盖。 :) – Vitus 2011-04-11 19:15:38

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 
相关问题