4

C++ Primer には、copy-control メンバーを使用してクラスを「値のように」動作させる例があります。つまり、オブジェクトをコピーする場合、コピーは独立しています。次のコードを提案します。

class HasPtrValue
{
public:
    HasPtrValue(const std::string &s = std::string()) : ps(new std::string(s)), i(0) {  }
    HasPtrValue(const HasPtrValue &orig) : ps(new std::string(*orig.ps)), i(orig.i) { }
    HasPtrValue& operator=(const HasPtrValue&);
    ~HasPtrValue() { delete ps; };

    std::string *ps;
    int i;
};

HasPtrValue& HasPtrValue::operator=(const HasPtrValue &rhs)
{
    auto newp = new std::string(*rhs.ps);
    delete ps;
    ps = newp;
    i = rhs.i;
    return *this;
}

私の質問は、コピー代入演算子に関するものです。私が理解しているように、ヒープに新しい文字列を作成し、古い文字列を削除し、lhs が新しい文字列を指すようにします。それは本当に必要ですか?以下のコードは、ヒープ上の既存の文字列に割り当てるだけでは、まったく同じことをしませんか?

HasPtrValue& HasPtrValue::operator=(const HasPtrValue &rhs)
{
    *ps = *rhs.ps;
    i = rhs.i;
    return *this;
}
4

2 に答える 2

2

あなたは正しいです。次のようにコピー代入演算子を定義するだけで十分です。

HasPtrValue& HasPtrValue::operator=(const HasPtrValue &rhs)
{
    *ps = *rhs.ps;
    i = rhs.i;
    return *this;
}

唯一の違い (新しいメモリの割り当てを除く) は、この場合、rhs オブジェクトの文字列は十分に小さくても、文字列に多くの予約済みメモリを含めることができることです。

C++ 標準では、コピー代入演算子を使用した場合に宛先文字列が元の文字列のサイズに縮小されるとは述べていません。と言うだけです

size() str.size()
capacity() a value at least as large as size()

元のバージョンに関しては、冗長なメモリ割り当てを回避するための自己割り当てがあるかどうかを確認する必要があります。つまり、次のようになります

HasPtrValue& HasPtrValue::operator=(const HasPtrValue &rhs)
{
    if ( this != &rhs )
    {
        auto newp = new std::string(*rhs.ps);
        delete ps;
        ps = newp;
        i = rhs.i;
    }

    return *this;
}
于 2015-02-24T20:11:41.680 に答える
2

あなたは正しいです。あなたのバージョンは動作するだけでなく、既存のメモリを再利用できるので効率的ps->capacity() >= rhs.ps->capacity()です.

強力な例外保証を提供したい場合は、copy-and-swap イディオムを使用する必要があります。

HasPtrValue& HasPtrValue::operator=(HasPtrValue copy) // notice the by value
{
    swap(*this, copy);
    return *this;
}

// integrating tip from link posted by WhozCraig 
friend void swap(HasPtrValue &lhs, HasPtrValue &rhs)
{
    using std::swap;
    swap(lhs.ps, rhs.ps);
    swap(lhs.i, rhs.i);
}

iの割り当てがコンパイラによって並べ替えられない限り、コードへの変更はすでに強力な例外保証を提供するはずですが。

于 2015-02-24T20:13:45.133 に答える