I've implemented a simple doubly linked list structure. I would appreciate all criticism relevant to code, style, flow, and so forth.
How to implement end iterator and pop_back/pop_front properly? Where memory may leak?
P.S.I didn't make it template, because this is simple version version.
#include <cstddef>
#include <iterator>
using T = int;
class List {
/// Nodes
public:
class Node {
public:
T data;
Node *next;
Node *prev;
public:
explicit Node(Node *next_, Node *prev_) : next(next_), prev(prev_) {}
explicit Node(const T &_data, Node *next_, Node *prev_) :
data(_data), next(next_), prev(prev_) {}
~Node() {}
};
///
/// Iterators
public:
class Iterator : public std::iterator<std::bidirectional_iterator_tag, T> {
public:
Node *position;
Node *tail;
public:
Iterator(Node *node) : position(node) {}
Iterator(Node *node, Node *_tail) : position(node), tail(_tail) {
}
Iterator &operator++() noexcept {
position = position->next;
return *this;
}
Iterator operator++(int) noexcept {
auto old = *this;
position = position->next;
return old;
}
Iterator &operator--() noexcept {
if (position == nullptr) position = tail;
else
position = position->prev;
return *this;
}
Iterator operator--(int) noexcept {
auto old = *this;
if (position == nullptr) position = tail;
else
position = position->prev;
return old;
}
T &operator*() const noexcept {
return (position->data);
}
bool operator!=(Iterator other) noexcept {
return position != other.position;
}
bool operator==(Iterator other) noexcept {
return position == other.position;
}
~Iterator() {}
};
///
/// list
private:
Node *head = nullptr;
Node *tail = nullptr;
size_t size_ = 0;
public:
List() {}
void push_back(const T &_data) {
Node *node = new Node(_data, nullptr, tail);
if (tail != nullptr) {
node->prev = tail;
tail->next = node;
tail = node;
} else {
head = tail = node;
}
++size_;
}
void push_front(const T &_data) {
Node *node = new Node(_data, head, nullptr);
if (head != nullptr) {
head->prev = node;
node->next = head;
head = node;
} else {
head = tail = node;
}
++size_;
}
void pop_back() {
tail = tail->prev;
if (tail != nullptr) {
tail->next = nullptr;
}
--size_;
}
void pop_front() {
head = head->next;
if (head != nullptr) {
head->prev = nullptr;
}
--size_;
}
size_t size() {
return size_;
}
size_t size() const {
return size_;
}
Iterator begin() {
return Iterator(head, tail);
}
Iterator begin() const {
return Iterator(head, tail);
}
Iterator end() {
Iterator iter(nullptr, tail);
return iter;
}
Iterator end() const {
Iterator iter(nullptr, tail);
return iter;
}
bool empty() const {
return head == nullptr;
}
~List() {
Node * tmp = nullptr;
while (head)
{
tmp = head;
head = head->next;
delete tmp;
}
head = tail = nullptr;
}
};
pop_front()
leaks. \$\endgroup\$pop_back()
\$\endgroup\$nullptr
won't release the memory. You need to call delete. Current code looks like freelist, not a list. \$\endgroup\$nullptr
to non deleted chunk of memory, you're basically saying "lets waste memory". I believe I gave enough information, good luck. \$\endgroup\$