2

コンストラクタ、デストラクタ、および代入演算子が適切に記述されていると仮定すると、次のようにコピー コンストラクタを実装できないのはなぜですか。

MyClass::MyClass(const MyClass &other)
{
    this->value = new Value(*(other.value));
}

私が見るほとんどの例は、これを行います:(通常、配列を扱っているため)

MyClass::MyClass(const MyClass &other)
{
    Value *temp = new Value;
    *temp = *(other.value);
    this->value = temp;
}

しかし、最初の例では、'new' がスローした場合、'other' は影響を受けず、Value のコピー コンストラクターがスローした場合、'new' は例外を伝播する前に割り当てられたメモリを解放しませんか?

これはミニ スマート ポインター自体のためであるため、特に std::unique_ptr やその他のスマート ポインターの使用を避けています。

4

2 に答える 2

2

また、Value のコピー コンストラクターがスローした場合、例外を伝播する前に、割り当てられたメモリを 'new' 解放しませんか?

はい。

3 行の割り当てバージョンの代わりに 1 行の方法を使用しない特別な理由はありません。


スマート ポインターを作成しているため、以下は適用されませんが、通常のクラスでは、手動ポインター管理を RAII 型にラップすることになるでしょう。std::unique_ptrそれはあなたが望むセマンティクスを持っているように見え、make_uniqueヘルパーはそれをかなり簡単にします:

#include <memory>

// probably will be added to the standard
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args &&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

class Value {};

class MyClass {
    std::unique_ptr<Value> value;

public:
    MyClass() : value{make_unique<Value>()} {}

    MyClass(MyClass const &other) : value{make_unique<Value>(*other.value)} {}

    MyClass &operator= (MyClass const &other) {
        value = make_unique<Value>(*other.value);
        return *this;
    }
    // you can also implement assignment from rvalue ref as an optimization
};
于 2013-03-18T02:27:44.310 に答える
1

列挙するには問題が多すぎます。3 つのルールを学ぶことをお勧めします。

私が言ったように、ここでの適切な解決策はおそらく読むでしょう

struct MyClass
{
     MyClass(const MyClass &other) : value(other.value) {}

    private:
     OtherClass value;
};

そして、ヒープ上に存在しなければならないvalueある種のリソースである場合、それは次のように宣言されます。

struct MyClass
{
    // ...
    private:
       std::unique_ptr<OtherClass> value;
};

そうすれば、所有権のセマンティクスとメモリ管理を (まあ、簡単に) 間違えることはありません。

于 2013-03-18T02:21:17.033 に答える