我在清理舊的C/C++應用程序的調試宏時遇到了這個問題:我們有一個Tracer類繼承自ostrstream
(我知道它自C++ 98以來已被棄用,但是這應用程序寫於1998年),我們使用這樣的:ostrstream將常量字符串解釋爲指針
Tracer() << "some" << " message" << " here";
現在,如果在鏈中的第一個值是一個常量字符串像上面,在示蹤調用ostrstream::str()
(這是在析構函數完成的結果,將結果插入到隊列中)包含指向此字符串的指針的十六進制表示而不是文本。因此,上述聲明將產生類似"0x401a37 message here"
的內容。這與舊的宏沒有發生,因爲它們總是有一個很長的(線程標識符)作爲現在已被刪除的第一個值。
用gdb進入它表明,對於第一次插入,這會在ostrstream上調用operator<<(void const*)
,而隨後的插入調用operator<< <...>(basic_ostream<...>&, char const*)
(爲了便於閱讀,刪除了模板)。
有人可以解釋這種行爲嗎?什麼將是一個乾淨的方法來解決這個問題?我找到了一個簡單的解決方法,它使用<< left
作爲第一個參數 - 這是否安全?有沒有更好的方法來做到這一點?
這裏的一個最小化的示例:
所有注意到operator<<
這需要
const char*
作爲參數是一個非成員函數的
#include <strstream>
#include <iostream>
using namespace std;
class Trace : public ostrstream {
public:
Trace();
virtual ~Trace();
};
Trace::Trace() : ostrstream() {}
Trace::~Trace() {
static_cast< ostrstream& >(*this) <<ends;
char * text = ostrstream::str();
cout << "MESSAGE: "<< text <<endl;
delete[] text;
}
int main(){
Trace() << "some" << " text" << " here";
Trace() << left << "some" << " text" << " here";
Trace() << 123 << " text" << " here";
}
感謝您的解釋 - 請參閱我對nawaz的回答的評論,對此的最佳解決方法是什麼? – l4mpi
不,標準的做法是像'Tracer()<< flush'來獲取流的左值引用。如果你有最新的編譯器之一,支持右值,它應該無論如何工作。這是C++ 11修訂版中修復的問題。 –
好的,謝謝。有問題的編譯器是g ++ 4.1.2 RedHat,它可悲地不符合C++ 11標準... – l4mpi