2016-05-31 7 views
0
class LinkedList 
{ 
public: 
    LinkedList() : _head(nullptr) {} 
    LinkedList(ListElement *newElement) : _head(newElement) {} 
    ~LinkedList() { }; 
    LinkedList(const LinkedList& LL); 
    LinkedList& operator=(LinkedList byValLinkedList); 
private: 
    ListElement *_head; 
} 
LinkedList::LinkedList(const LinkedList & LL) 
{ 
    ListElement *curr = LL._head; 

    // If Linked List is empty 
    if (isEmpty() && curr != nullptr) { 
     _head = new ListElement(curr->getValue()); 
     curr = curr->getNext(); 
    } 

    ListElement *newNode = nullptr; 
    while (curr) { 
     newNode = new ListElement(curr->getValue()); 
     curr = curr->getNext(); 
    } 
} 

LinkedList& LinkedList::operator=(LinkedList byValLinkedList) 
{ 

std::swap(_head, byValLinkedList._head); 
return *this; 
} 


int main() { 
    using namespace std; 
    LinkedList LL1(new ListElement(7)); 
    //..... some insertions 
    LinkedList LL2(new ListElement(5)); 
    //..... some insertions 
    LL1 = LL2; // What is the order ? 
    // ..... do something else 
    return 0; 
} 

LL1 = LL2は、1つが呼び出されると想定され、実行されます。コピー割り当ての前にコピーコンストラクタが呼び出されているのはなぜですか?

コピー割り当てが行われることを期待しています。しかし、コード、次の順序

  1. で実行されたコピーコンストラクタ
  2. コピーAssignemnt
  3. デストラクタ

は私が間違って何をしているのですか?デストラクタはなぜ呼ばれたのですか?

+0

、私は「あなたが実際に見てみたいことがあります推測すると思います。非常に広範ここにコピーおよびスワップイディオムの説明があります

コンストラクターの移動 "と"割り当ての移動 "を行います。 –

答えて

1
LinkedList& operator=(LinkedList byValLinkedList); 

あなたのコピーコンストラクタは、値によって、そのパラメータを取ります。これは

LL1=LL2; 

は値によってそれを渡すために、LL2のコピーを作成する必要があることを意味します。それは「価値あるものを通す」という意味です。したがって、コピーコンストラクタです。コピー構築を行うことを避けるために

は、代入演算子の代わりに、参照によりそのパラメータを取る必要があります。

意味
LinkedList& operator=(const LinkedList &byValLinkedList); 

、もちろんあれば、あなたはかなりstd::swapを使用して代入演算子を実装することはできません。しかし、それは別の質問になるでしょう...

簡潔に言うと、2つのコピーコンストラクタを実装します.1つはconst参照を取り、もう1つはstd::swapを使うことができます。または_headmutableと宣言します。

+0

コピーアンドスワップでは、コピーコンストラクタの呼び出しを避けたいと考えています。コピー操作(コピー代入とコピー構築)の両方をコピーコンストラクターで一度だけ実行する必要があります。 –

0

代入演算子byVallinkedListは値渡しです。そのLinkedListオブジェクトは、コピーコンストラクタを使用して初期化されます

1

あなたは何も間違っているわけではありません。これは、コピーアンドスワップが正常に動作する方法です。

コピーコンストラクタは、値渡しのパラメータを設定するために呼び出されます。そうでなければ、あなたのコピー代入演算子はコピーを作るためのコードを含まなければならないのですばらしいです。このようにして、コピーコンストラクタのロジックを再利用できます。

次に、パラメータが範囲外になり、関数の最後に破棄されます。スワップコールのため、このパラメータには、以前は*thisが保持していたリソースが含まれています。デストラクタはそれらを解放するので、非常に望ましいです。そうでなければ、代入によって置き換えられるデータを適切に取り除くためにコピー代入演算子のクリーンアップコードを記述する必要があります。

コードの再使用に加えて、コピーアンドスワップは例外的な安全性を提供します。コピーを左手オブジェクト(*this)に直接行った場合、何か問題が生じた場合は、すでに古い値を失ってしまい、物事を変更しないままにすることはできません。しかし、コピーアンドスワップを使用すると、コピーコンストラクタが最初に動作します。メモリが不足しているなど何かがうまくいかない場合、*thisは以前の値を保持します。std ::スワップに基づき

関連する問題