[解決済み] ダブルリンクリストテンプレート コピーコンストラクタ 代入演算子
2022-02-19 04:41:50
質問
C++でテンプレートを使って2重リンクリストの簡単な実装を書きました。しかし、コピーコンストラクタと代入演算子で問題が発生しました。私のコードはセグメンテーションフォールトを発生させ、それを修正する方法とエラーが発生する場所がわかりません(問題はコピーコンストラクタと代入演算子にあります)。
#include <iostream>
using namespace std;
template <class T>
class MyNode
{
public:
MyNode(const T &e = T(), MyNode *n = NULL, MyNode *p = NULL) : element(e), next(n), previous(p) {}
~MyNode() {}
T element;
MyNode *next;
MyNode *previous;
};
template <class T>
class MyList
{
private:
MyNode<T> *head;
MyNode<T> *tail;
public:
MyList()
{
head = new MyNode<T>();
tail = new MyNode<T>();
}
~MyList()
{
clear();
delete head;
delete tail;
}
MyList(const MyList& otherList)
{
while (otherList.head->next!=NULL)
{
MyNode<T> *curr = otherList.head->next;
insertLast(curr->element);
otherList.head->next = curr->next;
}
}
MyList& operator=(const MyList& otherList)
{
if(this == &otherList)
return *this;
while (otherList.head->next!=NULL)
{
MyNode<T> *curr = otherList.head->next;
insertLast(curr->element);
otherList.head->next = curr->next;
}
return *this;
}
bool isEmpty()
{
return (head->next == NULL);
}
void insertFirst(const T &e)
{
if (isEmpty())
{
MyNode<T> *newNode = new MyNode<T>(e);
head->next = newNode;
tail->previous = newNode;
}
else
{
MyNode<T> *actualFirst = head->next;
MyNode<T> *newNode = new MyNode<T>(e, actualFirst);
actualFirst->previous = newNode;
head->next = newNode;
}
}
void insertLast(const T &e)
{
if (isEmpty())
{
MyNode<T> *newNode = new MyNode<T>(e);
head->next = newNode;
tail->previous = newNode;
}
else
{
MyNode<T> *actualLast = tail->previous;
MyNode<T> *newNode = new MyNode<T>(e, NULL, actualLast);
actualLast->next = newNode;
tail->previous = newNode;
}
}
bool remove(MyNode<T> *r)
{
if (isEmpty())
{
return false;;
}
MyNode<T> *removeNode = tail->previous;
while (removeNode!=NULL)
{
if (removeNode==r)
{
break;
}
removeNode = removeNode->previous;
}
if (removeNode==NULL)
{
return false;
}
else
{
MyNode<T> *afterRemove = removeNode->next;
MyNode<T> *beforeRemove = removeNode->previous;
if (afterRemove==NULL)
{
tail->previous = beforeRemove;
}
else
{
afterRemove->previous = beforeRemove;
}
if (beforeRemove==NULL)
{
head->next = afterRemove;
}
else
{
beforeRemove->next = afterRemove;
}
delete removeNode;
return true;
}
}
void clear()
{
while (tail->previous!=NULL)
{
MyNode<T> *remove = tail->previous;
tail->previous = remove->previous;
delete remove;
}
}
void show()
{
while (head->next!=NULL)
{
MyNode<T> *curr = head->next;
std::cout << curr->element << "\n";
head->next = curr->next;
}
}
};
int main()
{
MyList<int> l1;
l1.insertLast(1);
l1.insertLast(2);
l1.insertLast(3);
//l1.show();
MyList<int> l2(l1);
//l2 = l1;
l2.show();
return 0;
}
解決方法は?
リストをコピーしたい場合、ディープコピーを行う必要があります。
MyList(const MyList& otherList)
{
if ( otherList.head == nullptr)
head = tail = nullptr; // if "otherList" is empty the new list is empty too.
else
{
head = new MyNode<T>( otherList.head ); // allocate head and copy data
MyNode<T> tempOther* = otherList.head->next;
MyNode<T> temp* = head;
while (tempOther != nullptr )
{
temp->next = new MyNode<T>( tempOther, nullptr, temp ); // allocate next elemnt and copy data ( predecessor is "temp" )
temp = temp->next; // temp refers to last element of list
tempOther = tempOther->next; // step one forward
}
tail = temp;
}
}
assigne演算子はコピーコンストラクタと似たような働きをします。
また
head
と
tail
.
head
は最初の要素へのポインタに過ぎず
tail
はリストの最後の要素へのポインタだけである。
MyList()
: head( nullptr )
, tail( nullptr )
{}
適応
isEmpty
,
insertFirst
と
insertLast
このように
bool isEmpty() { return head == nullptr); }
void insertFirst(const T &e)
{
if (isEmpty())
head = tail = new MyNode<T>(e);
else
{
MyNode<T> *newNode = new MyNode<T>(e, head, nullptr );
head->previous = newNode; // new node is predecessor of head
head = newNode ; // new head is new node
}
}
void insertLast(const T &e)
{
if (isEmpty())
head = tail = new MyNode<T>(e);
else
{
MyNode<T> *newNode = new MyNode<T>(e, nullptr, tail );
tail->next = newNode; // new node is successor of tail
tail = newNode ; // new tail is new node
}
}
アダプトメソッド
remove
をこのようにします。
bool remove(MyNode<T> *r)
{
MyNode<T> *removeNode = head;
while ( removeNode != nullptr ) // search the node to remove
{
if ( removeNode == r ) // break if node to remove is found
break;
removeNode = removeNode->next; // setp on forward
}
if ( removeNode == r ) // if node was found remove it
{
if ( removeNode == head )
head = removeNode->next; // if head is removed, new head is successor of head
if ( removeNode == tail )
tail = removeNode->previous; // if tail is removed, new tail is predecessor of tail
if ( removeNode->previous!= nullptr )
removeNode->previous->next = removeNode->next; // new succesor of predecessor is successor
if ( removeNode->next != nullptr )
removeNode->next->previous = removeNode->previous; // new prdecessor of successor is predecessor
delete removeNode;
return true;
}
return false;
}
最後に
clear
と
show
:
void clear()
{
MyNode<T> *curr = head;
while ( curr != nullptr )
{
MyNode<T> *del = curr;
curr = curr->next;
delete del;
}
head = tail = nullptr;
}
void show()
{
MyNode<T> *curr = head;
while ( curr != nullptr )
{
std::cout << curr->element << "\n";
curr = curr->next;
}
}
関連
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み】リンクリストのループを検出する方法は?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】C++の余分な資格エラー
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)