2

ストリーム (文字列、ファイル、またはメモリ) の反復処理を処理するために、かなり複雑な一連のクラスを作成しました。これらは標準ストリームではなく、関連もありません。とにかく、これらのバッファーを繰り返し処理し、バッファーに応じてアクションを実行するため、デバッガーで現在のバッファー位置を確認できるようにしたいと考えています。したがって、デバッグ上の理由だけで、ストリーム全体をベクターにコピーし、このベクター内の位置へのポインターを保持します。

次のコードは、前方反復子のように機能します。位置を保存し、後でそれを使用または更新できるようにする必要があります。このコードは問題を再現するためのものであることに注意してください。

class foo
{
public:
    foo ( std::string szTemp )
        : nOffset( 0 )
    {
        vec.resize( szTemp.size() );
        std::memcpy( &vec[ 0 ], szTemp.c_str(), szTemp.size() );
        pChar = &vec[ 0 ];
    }
    foo( const foo & Other )
        : vec( Other.vec )
        , nOffset( Other.nOffset )
    {
        pChar = &vec[ nOffset ];
    }

    void Inc ( void )
    {
        ++nOffset;
        pChar = &vec[ nOffset ];
    }

    size_t nOffset;
    char * pChar;
    std::vector< char > vec;
};

int _tmain ( int argc, _TCHAR* argv[] )
{
    foo a( "This is a temp string" );

    a.Inc();
    {
        foo b = a;
        b.Inc();
        a = b;
    } // Here is where the problem is seen
    a.Inc();
}

問題、b を a にコピーして戻した後、b.pChar の値が不正になります。

私が理解しているように、b は a からベクトルをコピーし、次に a は b からそれをコピーします。このコピーの後に pChar の値を設定したので、常に何かを指す必要があります。しかし、ベクトルが破壊されているように振る舞っています。

どうしたの?

4

3 に答える 3

2

他の2つの回答で述べたように、割り当てa = bの後、a.pCharを指しb.vecbスコープを離れたため、ダングリングポインターです。3 の規則 (C++11 の移動操作では 5 の規則) に従うか、 の格納を避けることでその規則を不要にする必要がありpCharますoffset

class foo
{
public:
    foo ( std::string szTemp )
        : nOffset( 0 )
    {
        vec.resize( szTemp.size() );
        std::coyp( begin(szTemp), end(szTemp), begin(vec) );
    }

    //special members:
    foo(foo const&)            = default;
    foo(foo&&)                 = default;
    foo& operator=(foo const&) = default;
    foo& operator=(foo&&)      = default;
    ~foo()                     = default;

    void Inc ( void )
    {
        ++nOffset;
    }

    char* pChar() //function instead of member variable!
    {
        return &vec[nOffset];
    }

    size_t nOffset;
    std::vector< char > vec;
};

このように、pChar()は常に と一貫性がnOffsetあり、特別なメンバーはデフォルトにする (または完全に省略する) ことができます。

于 2013-06-14T07:24:01.043 に答える