2012-07-06 91 views
6

我還在學習C++,所以請耐心等待。我在boost文件系統路徑上寫了一個簡單的包裝 - 我在返回臨時字符串時遇到了一些奇怪的問題。這是我簡單的類(這是不準確的,但相當接近):臨時std :: string返回垃圾

typedef const char* CString; 
typedef std::string String; 
typedef boost::filesystem::path Path; 

class FileReference { 

    public: 

     FileReference(const char* path) : mPath(path) {}; 

     // returns a path 
     String path() const { 
      return mPath.string(); 
     }; 

     // returns a path a c string 
     CString c_str() const { 
      return mPath.string().c_str(); 
     }; 

    private: 

     Path mPath; 

} 

與下面的小測試代碼:

FileReference file("c:\\test.txt"); 

OutputDebugString(file.path().c_str()); // returns correctly c:\test.txt 
OutputDebugString(file.c_str());  // returns junk (ie îþîþîþîþîþîþîþîþîþîþî.....) 

我敢肯定,這必須處理臨時工,但我不知道爲什麼會這樣 - 不是所有的東西都能正確複製?

+0

'OutputDebugString()'的來源是什麼? – 2012-07-06 19:28:08

+2

在'typedef'''ing你自己的'CString' ...上衝刺... – Blindy 2012-07-06 19:28:33

+1

@OttoAllmendinger - 它是[Windows API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363362( v = vs.85).aspx)函數。 – 2012-07-06 19:30:41

回答

4

看起來像mPath.string()按值返回字符串。只要FileReference :: c_str()返回,該臨時字符串對象就會被破壞,因此它的c_str()變得無效。使用這樣的模型,不可能創建一個c_str()函數,而不會爲字符串引入某種類或靜態級別的變量。

考慮以下方案:

//Returns a string by value (not a pointer!) 
//Don't call it c_str() - that'd be misleading 
String str() const 
{    
    return mPath.string(); 
} 

void str(String &s) const 
{    
    s = mPath.string(); 
} 
+0

第一個建議的有效用法是OutputDebugString(file.str())。 c_str());' – 2012-07-06 19:34:25

8
CString c_str() const { 
     return mPath.string().c_str(); 
    }; 

mPath.string()返回std::string的副本。該副本存儲在臨時表中,並在該表達式結尾處銷燬。

.c_str()返回指向內存的指針,當字符串被銷燬時,即該表達式結束時,該內存將被銷燬。

您正在返回一個已經銷燬的內存指針。

+1

如果他想要一個指針,他可以返回m_path.c_str() – PermanentGuest 2012-07-06 19:35:00

+0

@PermanentGuest - 你確定嗎?我在Boost.Filesystem [documentation]中找不到'.c_str()'(http://www.boost.org/doc/libs/1_41_0/libs/filesystem/doc/reference.html#Class-template- basic_path的)。 – 2012-07-06 19:39:59

+0

@Robᵩ:那些文檔已經快三年了。 [_current_ docs](http://www.boost.org/doc/libs/1_50_0/libs/filesystem/doc/reference.html#path-native-format-observers)提到它。 ; - ](這可能是在FileSystem v3中添加的。) – ildjarn 2012-07-06 19:44:19

0

表達式

OutputDebugString(file.path().c_str()) 

OutputDebugString(file.c_str()) 

很相似,它們都有效的調用臨時std::string對象c_str()方法,並嘗試使用該調用的結果。第一個直接稱爲file.path().c_str()子表達式。第二個更隱含:FileReference::c_str()方法。

在第一種情況下,std::string對象是由file.path()調用明確創建的,作爲整個表達式的直接部分。根據語言規則,該臨時對象的生命週期延伸到整個表達式的末尾,這就是爲什麼臨時對象和調用的結果始終保持有效的原因。

在第二種情況下,在FileReference::c_str()方法中創建臨時std::string對象。該方法返回時該臨時對象被銷燬,這意味着FileReference::c_str()返回指向「死」數據的指針。這是有關「垃圾」的原因。