[解決済み] 単一リンクリストでのコピーコンストラクタの実装 C++
質問
C++のコードを持っています。
#include <iostream>
using namespace std;
struct Node;
typedef Node *NodePtr;
struct Node
{
int Item;
NodePtr Next;
};
class LinkedList
{
public:
LinkedList(); // default constructor
~LinkedList(); // destructor
void AddTail(int); // adds item to tail
private:
NodePtr Head;
};
LinkedList::LinkedList()
{
Head = NULL; //declare head as null
}
//Adding on tail
void LinkedList::AddTail(int Item)
{
NodePtr Crnt;
NodePtr node = new Node;
node->Item = Item;
node->Next = NULL;
//if head is in null declare the added node as head
if (Head == NULL)
{
Head = node;
}
else
{ //set the current to head, move the current node to current next node
Crnt = Head;
while (Crnt->Next != NULL)
{
Crnt = Crnt->Next;
}
//Add item to the tail of the linked list
Crnt->Next = node;
}
}
int main()
{
LinkedList la;
la.AddTail(30);
la.AddTail(60);
la.AddTail(90);
LinkedList lb;
return 0;
}
そこで質問ですが、リストの引数のディープコピーを作成するコピーコンストラクタ(オブジェクトlbを想定)をどのように実装し、また、空と空でないリストでコピーコンストラクタをテストするコードを追加すれば良いでしょうか? 事前にありがとうございます。
どのように解決するのですか?
プログラミングの大きなルールのひとつにDRY(Don't Repeat Yourself)があります。もし、足し算をする関数があって、それがうまくいくことが分かっているなら、足し算関連の仕事のためにそれを使い続けましょう。つまり、addの死語と汎用性を保つことが得策なのです。
DRYの考え方を応用して、コピーコンストラクタを想定した
AddTail
メソッドが正しく機能するようになり、驚くほどシンプルになりました。を呼び出すだけです。
AddTail
をソースリスト内のすべてのノードに適用します。
LinkedList::LinkedList(const LinkedList & src):Head(nullptr)
{
NodePtr node = src.Head;
while (node != nullptr)
{
AddTail(node->Item);
node = node->Next;
}
}
また、コピーコンストラクタが動作していることで、代入演算子は コピーとスワップのイディオム これも笑えるほど簡単です。
LinkedList & LinkedList::operator=(LinkedList src)
// pass by reference performs the copy
{
std::swap(Head, src.Head); // now just swap the head of the copy
// for the head of the source
return *this;
} // destructor fires for src and cleans up all the nodes that were on this list
仕上げに
3つのルール
三拍子揃ったデストラクタが必要です。これは
コピーコンストラクタはDRYの応用で、リストが空になるまで何度もノードの削除関数を呼び出すことができます。削除関数はどんなリンクリストでもほぼ確実に必要なものなので、ここでは
Remove
.
LinkedList::~LinkedList()
{
while (Head != nullptr)
{
NodePtr temp = Head;
Remove(Head);
delete temp;
}
}
このように、Linked Listはとにかくこの2つの関数がないと機能しないので、これをベースに、基本的なメンテナンスに必要な他の関数をすべて実装しました。必要なのは、テスト済みでバグのない
Add
と
Remove
という関数があり、それ以外は実質的に無償で提供されます。
また
AddTail
関数は、私の苦手なものに当たるのですが...。ここでは、この関数の複雑さを大幅に軽減するトリックを紹介します。
void LinkedList::AddTail(int Item)
{
NodePtr *Crnt = &Head; // instead of pointing where Head points, point at
// Head now we don't care if it is head or any
// other node's Next. They are all abstracted to
// the same thing: A pointer to where the next
// node can be found
while (*Crnt != NULL) // keep looking until end of list
{
Crnt = &(*Crnt)->Next; // by pointing at the next Next pointer
}
//Add item to the tail of the linked list
NodePtr node = new Node;
node->Item = Item;
node->Next = NULL;
*Crnt = node; // Now just plop the new node over top of the terminating NULL
}
は
Remove
関数も同じようにポインタ-to-ポインタのトリックを使っています。
関連
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] C++で、あるコンストラクタを別のコンストラクタから呼び出す(コンストラクタ・チェイニングを行う)ことは可能ですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] Java で、あるコンストラクタを別のコンストラクタから呼び出すにはどうすればよいですか?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] C#でベースコンストラクタを呼び出す
-
[解決済み] コンストラクタ内の仮想メンバー呼び出し
-
[解決済み] あるコンストラクタを別のコンストラクタから呼び出す
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?