簡體   English   中英

使用std :: vector的不尋常行為

[英]Unusual behavior with std::vector

我編寫了一組相當復雜的類來處理迭代流(字符串,文件或內存)。 這些不是標准流,也不是相關的。 無論如何,由於迭代這些緩沖區並根據緩沖區執行操作,我希望能夠在調試器中看到當前的緩沖區位置。 因此,僅出於調試原因,我將整個流復制到向量並保持指向此向量中位置的指針。

以下代碼的作用類似於前向迭代器。 我需要能夠存儲一個位置,然后使用它或更新它。 請注意,此代碼僅用於復制問題。

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復制回到然后踩出之后,b.pChar的值變為非法。

據我了解,b從a復制矢量,然后又從b復制它。 因為我在這個副本之后設置了pChar的值,它應該總是指向某個東西。 但是,它就像矢量被摧毀一樣。

這是怎么回事?

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

你的問題在這里。

a = b;

請求調用賦值運算符,表示您沒有實現,因此,默認值將執行成員賦值。 在此之后,你的char pointer將是懸空指針。 以下代碼將做正確的工作。

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 ];
    }
    foo& operator = (const foo& other)
    {
       foo tmp(other);
       swap(tmp);
       return *this;
    }

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

    void Swap(foo& other)
    {
       std::swap(vec, other.vec);
       std::swap(nOffset, other.nOffset);
       std::swap(pChar, other.pChar);
    }

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

你的班級不遵循三條規則 您有自定義復制構造函數,但不是自定義賦值運算符(並且沒有自定義析構函數,但此特定類可能不需要它)。 這意味着foo b = a; 做你想要的(稱你的副本ctor),但a = b; 沒有(調用默認賦值op)。

正如在另外兩個答案中所提到的,在他指定a = ba.pChar指向b.vec ,並且由於b已經離開范圍,因此它是一個懸空指針。 您應該遵守三條規則(使用C ++ 11的移動操作的五條規則),或者通過避免存儲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一致,並且特殊成員可以只是默認(或完全省略)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM