6

私はまだc++を学んでいるので、我慢してください。ブーストファイルシステムパスの周りに単純なラッパーを書いています-一時的な文字列を返す際に奇妙な問題が発生しています。これが私の単純なクラスです(これは正確ではありませんが、かなり近いです):

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 îþîþîþîþîþîþîþîþîþîþî.....)

これは一時的なものに対処する必要があると確信していますが、なぜそうなるのか理解できません。すべてが正しくコピーされているべきではないでしょうか。

4

3 に答える 3

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

mPath.string()のコピーを返しますstd::string。そのコピーは一時的に保存され、この式の最後で破棄されます。

.c_str()文字列が破棄されたとき、つまりこの式の最後に破棄されるメモリへのポインタを返します。

すでに破棄されているメモリへのポインタを返しています。

于 2012-07-06T19:32:20.907 に答える
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();
} 
于 2012-07-06T19:29:26.137 に答える
0

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

OutputDebugString(file.c_str())

どちらもc_str()一時std::stringオブジェクトのメソッドを効果的に呼び出し、その呼び出しの結果を使用しようとするという点で似ています。最初のものはそれをfile.path().c_str()部分式として直接呼び出します。2つ目は、より暗黙的にそれを行います:FileReference::c_str()メソッド内。

最初のケースでは、一時std::stringオブジェクトはfile.path()、式全体の直接の一部として呼び出しによって明示的に作成されます。言語の規則に従って、その一時オブジェクトの存続期間は式全体の終わりまで延長されます。そのため、一時オブジェクトとc_str()呼び出しの結果は全体を通して有効なままです。

2番目のケースでは、一時std::stringオブジェクトはFileReference::c_str()メソッド内に作成されます。この一時オブジェクトは、このメソッドが戻ると破棄されます。つまり、FileReference::c_str()「デッド」データへのポインタが返されます。これが問題の「ジャンク」の理由です。

于 2012-07-06T20:46:56.240 に答える