2012-04-23 91 views
0

我已經失去了一個小時找到我的代碼這個問題:引用到一個臨時和警告

vector<string> & input_variables = parse_xml(xml_path)["variables"]; 

其中parse_xml是返回std::map<std::string, std::vector<std::string> >的功能。爲什麼gcc沒有警告我(帶-Wall)?我錯過了一些標誌?

+0

[插入'valgrind'或類似工具的廣告]。不,但真的,它會爲自己節省時間學習使用它們;)。 – FatalError 2012-04-23 16:33:50

+0

請您列出您的完整編譯標誌。特別是您的警告標誌 – 111111 2012-04-23 16:34:10

+0

臨時的生命週期不應該延長,因爲12.2/5表明? – sharptooth 2012-04-23 16:34:21

回答

2

您已經引用了一個被銷燬的對象。在C++ 11中,新語言功能是爲了使代碼非法而編寫的。如果你想使用它,你必須複製或交換數據到一個局部變量。 GCC沒有警告你,因爲C++ 03沒有提供必要的功能來防止這種情況。

從技術上講,operator[]的返回值是一個左值。不幸的是,它將被它的主人std::map摧毀。

+0

您確定這將在C++ 11中無效嗎?這裏的問題的確是'parse_xml'的返回是一個臨時對象,而不是一個常量對象。 – 2012-04-23 16:59:58

+0

我正在使用C++ 03 – 2012-04-23 21:08:18

+0

@Let_Me_Be:在C++ 11中,可以基於左值或右值重載成員函數(包括operator [])。這意味着'operator []'可以返回一個臨時的 - 正確地阻止這個代碼。 'const'與此完全無關。 – Puppy 2012-04-23 21:33:41

0

它爲什麼不提醒你的原因是因爲你是通過有效的步驟序列獲得的無效操作:

struct X 
{ 
    int c; 
    int & operator [] (int) { return c; } /* this is perfectly OK */ 
}; 

X f() 
{ 
    return X(); /* this is perfectly OK */ 
} 

int main() 
{ 
    int &x = f()[1]; /* can apply [] on temporary, therefore OK */ 
} 

可以防止這種通過明確標記的f()作爲const結果發生。

+0

'const' rvalues是不好的。例如,它們不能被移動。 – Puppy 2012-04-23 21:34:30

+0

@DeadMG在ANSI C++? – 2012-04-24 10:34:26

+0

ANSI? ANSI從不標準化任何版本的C++。目前只有ISO C++ - 去年標準化的當前版本。 – Puppy 2012-04-24 11:29:37

1

海灣合作委員會並沒有警告你,因爲技術上沒有什麼可警告的。

parse_xml()按值返回std::map,這是一個臨時值。調用operator[]返回一個參考。編譯器不能知道本地該參考實際上是部分std::map臨時。對於所有的編譯器都知道,operator[]可能會返回一個對全局或其他東西的引用。

臨時成員變量被認爲是臨時的,它與外部臨時的生命週期相關聯。但是函數的返回值(如operator[])是而不是這樣鏈接。