작성
·
339
·
수정됨
0
#include <iostream>
using namespace std;
#include <list>
//양방향 리스트, 링크드 리스트.
template<class T>
class Node {
public:
Node() : _next(nullptr), _prev(nullptr), _data(T()) {
}
Node(const T& value) : _next(nullptr), _prev(nullptr), _data(value)
{
}
public:
Node* _next;
Node* _prev;
T _data;
};
template<class T>
class Iterator
{
public:
Iterator() : _node(nullptr)
{
}
Iterator(Node<T>* data) : _node(data) {
}
Iterator<T>& operator++()
{
_node = _node->_next;
return *this;
}
Iterator<T> operator++(int)
{
Iterator<T> temp = *this;
_node = _node->_next;
return temp;
}
Iterator<T>& operator--() {
_node = _node->_prev;
return *this;
}
Iterator<T> operator--(int)
{
Iterator<T> temp = *this;
_node = _node->_prev;
return temp;
}
T& operator*()
{
return _node->_data;
}
bool operator==(const Iterator& right)
{
return _node == right._node;
}
bool operator!=(const Iterator& right)
{
return !(*this == right);
}
public:
Node<T>* _node;
};
//[1]->[2]->[3]->[4]->[header]가 빈 깡통이어도 기본
template<class T>
class List {
public:
typedef Iterator<T> iterator;
List() :_size(0)
{
_header = new Node<T>();
_header->_next = _header;
_header->_prev = _header;
}
~List() {
//TODO
while (_size > 0)
pop_back();
delete _header;
}
void push_back(const T& value)
{
AddNode(_header, value);
}
// [1] <-> [2] <-> 3 <->[header]
// [1] <-> [2] <-> [ header ]
void pop_back()
{
RemoveNode(_header->_prev);
}
iterator insert(iterator iter, T _data)
{
return iterator(AddNode(iter._node, _data));
}
iterator erase(iterator iter)
{
Node<T>* target = RemoveNode(iter._node);
return iterator(target);
}
private:
Node<T>* AddNode(Node<T>* before, const int& value)
{
Node<T>* newNode = new Node<T>(value);
Node<T>* prevNode = before->_prev;
prevNode->_next = newNode;
newNode->_next = before;
before->_prev = newNode;
newNode->_prev = prevNode;
++_size;
return newNode;
}
Node<T>* RemoveNode(Node<T>* target)
{
Node<T>* prevNode = target->_prev;
Node<T>* nextNode = target->_next;
prevNode->_next = nextNode;
nextNode->_prev = prevNode;
--_size;
delete target;
return nextNode;
}
public:
iterator begin() { return iterator(_header->_next); }
iterator end() { return iterator(_header); }
int size() { return _size; }
public:
Node<T>* _header;
int _size;
};
template<class T>
void test(T);
int main() {
/*List<int> li;
List<int>::iterator eraseIt;
for (int i = 0; i < 10; i++)
{
if (i == 5) {
eraseIt = li.insert(li.end(), i);
}
else
{
li.push_back(i);
}
}
li.pop_back();
li.erase(eraseIt);
for (auto i = li.begin(); i != li.end(); ++i)
{
cout << *i << endl;
}*/
test(List<int>());
}
template<class T>
void test(T) {
T li;
T::template iterator eraseIt;
for (int i = 0; i < 10; i++)
{
if (i == 5) {
eraseIt = li.insert(li.end(), i);
}
else
{
li.push_back(i);
}
}
li.pop_back();
li.erase(eraseIt);
for (auto i = li.begin(); i != li.end(); ++i)
{
cout << *i << endl;
}
}
해당 코드에서 main에서 주석으로 처리한 부분은 잘 되는데 template로 작성한 펑션이 끝나면 Invalid address specified to RtlValidateHeap 크래쉬가 나는데 이유가 궁금합니다.. ㅠ
답변 1
1
리스트를 연습용으로 한 것이라 완전하지 않고
operator= 등의 복사에 대한 처리가 안 되어 있습니다.
test(List<int>());
여기서 임시 리스트를 만들어서 복사를 하고 있는데
그럴 경우 기본 헤더와 size 등이 [얕은 복사]로 넘어가서
동일한 헤더를 두 번 지우게 됩니다.
template<class T>
void test(T& li); 로 해서 왼값을 넘기거나
void test(T&& li); 로 해서 오른값을 넘기는 식으로 수정하시면 됩니다.