fork download
  1. #include <cassert>
  2. #include <iostream>
  3. #include <memory>
  4.  
  5. using namespace std;
  6.  
  7. class List {
  8. public:
  9. List() = default;
  10. // ~List() = default; also works.
  11. ~List() {
  12. cout << "Enter List destructor\n";
  13. // Release |front_| explicitly to see how the Node is released.
  14. front_ = nullptr;
  15. cout << "List destructor done\n";
  16. }
  17.  
  18. int front() const {
  19. assert(front_);
  20.  
  21. return front_->element;
  22. }
  23.  
  24. bool empty() const {
  25. return size_ == 0;
  26. }
  27.  
  28. size_t size() const {
  29. return size_;
  30. }
  31.  
  32. void push_front(int element) {
  33. unique_ptr<Node> new_front = make_unique<Node>(element, move(front_));
  34.  
  35. front_ = move(new_front);
  36. size_++;
  37. }
  38.  
  39. void pop_front() {
  40. front_ = move(front_->next_node);
  41. size_--;
  42. }
  43.  
  44. void insert_at(int index, int element) {
  45. assert(index <= size_);
  46.  
  47. // |front_| will be updated to the new node. Handle it separately.
  48. if (index == 0) {
  49. push_front(element);
  50. return;
  51. }
  52.  
  53. // Here we don't need the ownership of the node when finding the insert
  54. // point. Just use the raw pointer.
  55. Node* front_node = front_.get();
  56. for (size_t i = 0; i < index - 1; i++) {
  57. front_node = front_node->next_node.get();
  58. }
  59.  
  60. unique_ptr<Node> new_node = make_unique<Node>(
  61. element, move(front_node->next_node));
  62. front_node->next_node = move(new_node);
  63. size_++;
  64. }
  65.  
  66. void print() const {
  67. // We don't need the ownership of the node when triversing the list.
  68. // Just use the raw pointer.
  69. Node* p = front_.get();
  70. while (p != nullptr) {
  71. cout << p->element << " -> ";
  72. p = p->next_node.get();
  73. }
  74. cout << "NULL" << endl << "size = " << size_ << endl;
  75. }
  76.  
  77. private:
  78. // The list client doesn't need to know the detail about Node, so put it in
  79. // private. Node only has public data members. Just use struct.
  80. struct Node {
  81. Node(int e, unique_ptr<Node> n)
  82. : element(e), next_node(move(n)) {}
  83. ~Node() {
  84. cout << "Node " << element << " is released.\n";
  85. }
  86.  
  87. int element;
  88. unique_ptr<Node> next_node;
  89. };
  90.  
  91. unique_ptr<Node> front_;
  92. size_t size_ = 0;
  93. };
  94.  
  95. int main() {
  96. List myList;
  97. myList.push_front(23);
  98. myList.push_front(24);
  99. myList.push_front(25);
  100. myList.push_front(27);
  101. myList.push_front(2);
  102. myList.push_front(32);
  103. myList.print();
  104. myList.insert_at(4, 89);
  105. myList.print();
  106. myList.pop_front();
  107. myList.print();
  108.  
  109. cout << "Exit main(). After that List destructor will be triggered.\n";
  110. return 0;
  111. }
Success #stdin #stdout 0s 4304KB
stdin
Standard input is empty
stdout
32 -> 2 -> 27 -> 25 -> 24 -> 23 -> NULL
size = 6
32 -> 2 -> 27 -> 25 -> 89 -> 24 -> 23 -> NULL
size = 7
Node 32 is released.
2 -> 27 -> 25 -> 89 -> 24 -> 23 -> NULL
size = 6
Exit main(). After that List destructor will be triggered.
Enter List destructor
Node 2 is released.
Node 27 is released.
Node 25 is released.
Node 89 is released.
Node 24 is released.
Node 23 is released.
List destructor done