2013-10-20 69 views
2

是否有任何解釋在標準的以下行爲?C++ Odox行爲與ostringstream

下面的代碼:

#include <sstream> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    ostringstream os1; 
    ostringstream os2; 

    os1 << 1 << " " << 2; 
    os2 << 1 << " " << 2 << " " << 3; 

    const char *p = os1.str().c_str(); 

    cout << os2.str() << endl; 
    cout << p << endl; 

    return 0; 
} 

顯示輸出:

不過,我期待它顯示:

1 2 3 
1 2 

看起來OS1對象以某種方式影響通過os2,如果我刪除os2.str()調用,則示例行爲正確。

我已經嘗試過這個例子,如果Solaris Studio 12.2和G ++ 4.8.1和兩者的行爲方式相同。

感謝您的幫助!

+0

奇怪的是,此代碼在我的機器w/g ++上打印「1 2 3 \ n1 2 \ n」。 – jma127

+0

試試這裏:http://www.compileonline.com/compile_cpp_online。php –

+0

@ jma127我在Debian上使用g ++ 4.8.1得到了同樣奇怪的結果,例如P.An. – PhillipD

回答

3
const char *p = os1.str().c_str(); 

這是上述問題。

os1.str()通過複製內部字符串緩衝區來返回臨時字符串對象。並且您正在採取臨時對象的.c_str(),該對象在完整表達式的末尾被破壞。結果是,當您使用std::cout進行打印時,p指向被破壞的對象。

也就是說,你的程序調用未定義的行爲(UB)。

試試這個:

auto s = os1.str(); 
const char *p = s.c_str(); //s is not a temporary object anymore! 

現在它給correct output(這是your code —幸運的是,即使coliru提供同樣的輸出爲您的機器上發現注意,這個輸出是保證,雖然。正是因爲代碼調用了UB)。

+0

非常感謝您的幫助! –

2

我認爲這個問題與保留由c_str()返回的指針有關。

ostringstream::str()正在返回一個臨時字符串對象,並且您正在保存一個指向其內部char數組的指針。但是一旦該行被執行,返回的字符串對象將被刪除。所以你的指針將是無效的。

如果你想保持一個c_str圍繞指針出於某種原因,你就還需要保留字符串的副本:

string s = os1.str(); 
const char *p = s.c_str(); 

cout << os2.str() << endl; 
cout << p << endl; 
+1

它看起來像保持一個引用也工作,如果我以下面的方式更改代碼,它顯示正常:const std :: string&s = os1.str(); const char * p = s.c_str(); –

0

的這個問題的答案就在這裏: stringstream, string, and char* conversion confusion

stringstream.str()返回一個在完整表達式結束時被銷燬的臨時字符串對象。如果你從(stringstream.str()。c_str())中得到一個指向C字符串的指針,它將指向一個在語句結束時被刪除的字符串。