I am an experienced C# developer and started with C++ a few days ago. I implemented a simple linked list to play around with templates, iterators, pointers, references and stuff.
What would experienced C++ developers do differently?
Thread-safety and performance were not a priority in this implementation. I wanted it to work and to be written C++-style, not C#-style.
#include <stdint.h>
#include <iostream>
template<class T>
class LinkedList final {
public:
LinkedList();
LinkedList(const LinkedList<T> &src);
LinkedList(const LinkedList<T> &&src);
LinkedList &operator=(const LinkedList &src);
LinkedList &operator=(const LinkedList &&src);
void Add(const T &value);
void Remove(std::uint32_t index);
T Get(std::uint32_t index) const;
void Print() const;
std::uint32_t GetCount() const;
private:
struct ListNode {
ListNode(const T value) : value_(value), next_(nullptr) {
}
~ListNode() {
}
ListNode* next_;
T value_;
};
std::uint32_t count_;
ListNode* start_;
ListNode* end_;
public:
struct iterator {
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
iterator(ListNode* init = nullptr) : current_(init) {}
T& operator*() {
return current_->value_;
}
const T& operator*() const {
return current_->value_;
}
iterator& operator++() { // prefix
if (current_ != nullptr)
current_ = current_->next_;
return *this;
}
iterator operator++(int) { // postfix
iterator temp = *this;
++*this;
return temp;
}
bool operator==(const iterator& x) const {
return current_ == x.current_;
}
bool operator!=(const iterator& x) const {
return current_ != x.current_;
}
private:
ListNode * current_;
};
iterator begin() {
return iterator(start_);
}
iterator end() {
return iterator();
}
};
template<class T>
inline LinkedList<T>::LinkedList(): start_(nullptr), end_(nullptr), count_(0) {
}
template<class T>
inline LinkedList<T>::LinkedList(const LinkedList<T>& src)
: start_(nullptr), end_(nullptr), count_(0) {
for (auto node_iter = src.start_; node_iter != nullptr; node_iter = node_iter->next_)
{
Add(node_iter->value_);
}
}
template<class T>
inline LinkedList<T>::LinkedList(const LinkedList<T>&& src) : count_(src.count_), start_(src.start_), end_(src.end_) {
}
template<class T>
inline LinkedList<T> & LinkedList<T>::operator=(const LinkedList & src) {
auto delete_iter = start_;
while (delete_iter != nullptr) {
start_ = start_->next_;
delete delete_iter;
delete_iter = start_;
}
for (auto node_iter = src.start_; node_iter != nullptr; node_iter = node_iter->next_)
{
Add(node_iter->value_);
}
return *this;
}
template<class T>
inline LinkedList<T> & LinkedList<T>::operator=(const LinkedList &&src) {
count_ = src.count_;
start_ = src.start_;
end_ = src.end_;
return *this;
}
template<class T>
inline void LinkedList<T>::Add(const T &value) {
if (start_ == nullptr) {
start_ = new ListNode(value);
end_ = start_;
}
else {
end_->next_ = new ListNode(value);
end_ = end_->next_;
}
count_++;
}
template<class T>
inline void LinkedList<T>::Remove(std::uint32_t index) {
if (index >= count_) {
throw std::out_of_range("Index was larger than list length.");
}
count_--;
if (index == 0) {
auto old_start = start_;
start_ = start_->next_;
if (count_ == 1)
end_ = nullptr;
delete old_start;
return;
}
auto current = start_;
while (--index > 0)
{
current = current->next_;
}
auto next = current->next_;
current->next_ = next->next_;
if (end_ == next) {
end_ = current;
}
delete next;
}
template<class T>
inline T LinkedList<T>::Get(std::uint32_t index) const {
if (index >= count_) {
throw std::out_of_range("Index was larger than list length.");
}
auto current = start_;
while (index-- > 0) {
current = current->next_;
}
return current->value_;
}
template<class T>
inline void LinkedList<T>::Print() const {
if (start_ == nullptr) {
std::cout << "[empty]" << std::endl;
return;
}
auto current = start_;
while (current->next_ != nullptr)
{
std::cout << current->value_ << " - ";
current = current->next_;
}
std::cout << current->value_ << std::endl;
}
template<class T>
inline std::uint32_t LinkedList<T>::GetCount() const {
return count_;
}