2
std::string t1("aaa");
const char *p = t1.c_str();
std::string t2(std::move(t1));
if (p == t2.c_str()) {
    std::cout << "ok!" << std::endl;    
}

このコードは、vs2012 では何も出力しませんでした。文字列をにmemmoveコピーするために内部的に使用するだけです。なんで?t1t2

4

3 に答える 3

9

正式には、jrok が指摘したように、あなたがしていることは未定義の動作であるため、実装が何を行っても文句を言う権利はありません。実際には、実装に依存します。標準では、移動コンストラクターがstd::stringソース文字列に関して何かを行う必要はありません。実装が小さな文字列の最適化を使用し (たとえば、VC++ がそうであるように)、文字列が修飾するのに十分小さい場合、文字を memcpy する以外に何する方法はありません 。彼らはchar[]文字列オブジェクト自体。CoW の実装 (g++ のようなもの) は、わざわざする価値がないという理由で、コピー コンストラクターで行うことと何も変わらないかもしれません。あなたは本当に多くを節約しません。(しかし、ポインターを交換するだけで少し節約できるので、そうなるかもしれません。)

VC++で同じことを試しましたが、文字列は100文字です。それはスワップを行いました(そして2つのポインタは等しかったです)。したがって、VC++ の動作は、文字列が SSO を適用するのに十分小さいかどうかによって異なります。すべてのケースで G++ スワップ。

于 2013-08-15T10:32:56.233 に答える
3

Visualtudioは実際にポインターを移動する前に文字列の長さを比較し、std::moveコードにデバッグすることで、長さの文字列をコピーしたことが16バイト未満であることを示しています

void _Assign_rv(_Myt&& _Right)
{   
   // assign by moving _Right
   if (_Right._Myres < this->_BUF_SIZE)  //_BUF_SIZE is 16, comment mine
       _Traits::move(this->_Bx._Buf, _Right._Bx._Buf,
       _Right._Mysize + 1);
   else
   {    // copy pointer
    this->_Getal().construct(&this->_Bx._Ptr, _Right._Bx._Ptr);
    _Right._Bx._Ptr = pointer();
    }
    this->_Mysize = _Right._Mysize;
    this->_Myres = _Right._Myres;
    _Right._Tidy();
}
于 2013-08-15T10:24:18.110 に答える