2011-04-09 30 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 
相關問題