From 171475b4df01c7d523b68ce190a2c2a6e287a42c Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 24 Mar 2022 20:34:22 +0800 Subject: [PATCH 1/2] complete hw02 --- main.cpp | 112 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/main.cpp b/main.cpp index dc25c6b..75ae183 100644 --- a/main.cpp +++ b/main.cpp @@ -3,52 +3,81 @@ #include struct Node { - // 这两个指针会造成什么问题?请修复 - std::shared_ptr next; - std::shared_ptr prev; + /* Q: 这两个指针会造成什么问题? + A: 产生了环形引用,导致无法解构。 */ + std::unique_ptr next; + struct Node* prev; // 如果能改成 unique_ptr 就更好了! int value; - // 这个构造函数有什么可以改进的? - Node(int val) { + /* Q: 这个构造函数有什么可以改进的? + A: 添加 explicit 避免隐式转换。 */ + explicit Node(int val) { value = val; } void insert(int val) { - auto node = std::make_shared(val); - node->next = next; + auto node = std::make_unique(val); node->prev = prev; - if (prev) - prev->next = node; if (next) - next->prev = node; + next->prev = node.get(); + if (prev) + prev->next = std::move(node); + node->next = std::move(next); } void erase() { if (prev) - prev->next = next; + prev->next = std::move(next); if (next) next->prev = prev; } ~Node() { - printf("~Node()\n"); // 应输出多少次?为什么少了? + /* Q: 应输出多少次?为什么少了? + A: 产生了环形引用,导致无法解构。 */ + printf("~Node(%d)\n", value); } }; struct List { - std::shared_ptr head; + std::unique_ptr head; + struct Node* tail; - List() = default; + List() { + auto node_tail = std::make_unique(0); + tail = node_tail.get(); + head = std::move(node_tail); + }; List(List const &other) { printf("List 被拷贝!\n"); - head = other.head; // 这是浅拷贝! // 请实现拷贝构造函数为 **深拷贝** + auto node_tail = std::make_unique(0); + tail = node_tail.get(); + head = std::move(node_tail); + std::unique_ptr* last = nullptr; + for (auto curr = other.front(); curr != other.tail; curr = curr->next.get()) { + auto node = std::make_unique(curr->value); + if (last == nullptr) { + node->next = std::move(head); + head = std::move(node); + last = &head; + } else { + node->next = std::move((*last)->next); + node->prev = last->get(); + (*last)->next = std::move(node); + last = &((*last)->next); + } + tail->prev = last->get(); + } } - List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? + /* Q: 为什么删除拷贝赋值函数也不出错? + A: 因为这相当于使用拷贝构造函数就地构造出对象,从而进一步调用移动赋值函数完成整个过程。 + 如果使用 explicit 关键词修饰拷贝构造函数,则会产生编译错误。 */ + List &operator=(List const &) = delete; List(List &&) = default; List &operator=(List &&) = default; @@ -59,16 +88,23 @@ struct List { int pop_front() { int ret = head->value; - head = head->next; + if (head->next.get() == tail) { + head = nullptr; + tail->prev = nullptr; + } else { + head = std::move(head->next); + } return ret; } void push_front(int value) { - auto node = std::make_shared(value); - node->next = head; + auto node = std::make_unique(value); if (head) - head->prev = node; - head = node; + head->prev = node.get(); + else + tail->prev = node.get(); + node->next = std::move(head); + head = std::move(node); } Node *at(size_t index) const { @@ -78,12 +114,37 @@ struct List { } return curr; } + + class iterator : public std::iterator { + Node *node; + + public: + explicit iterator(Node *_node) : node(_node) {} + iterator &operator++() { + node = node->next.get(); + return *this; + } + iterator operator++(int) { + iterator retval = *this; + ++(*this); + return retval; + } + bool operator==(iterator other) const { return node == other.node; } + bool operator!=(iterator other) const { return !(*this == other); } + reference operator*() const { return node->value; } + }; + iterator begin() { return iterator(head.get()); } + iterator end() { return iterator(tail); } }; -void print(List lst) { // 有什么值得改进的? + +/* Q: 有什么值得改进的? + A: 改为引用传递,减少一次深拷贝。 */ +void print(List &lst) { printf("["); - for (auto curr = lst.front(); curr; curr = curr->next.get()) { - printf(" %d", curr->value); + for (auto it = lst.begin(); it != lst.end(); it++) { + printf(" %d", *it); } printf(" ]\n"); } @@ -112,8 +173,11 @@ int main() { print(a); // [ 1 4 2 5 7 ] print(b); // [ 1 4 2 8 5 7 ] + puts("------------"); b = {}; + puts("------------"); a = {}; + puts("------------"); return 0; } From feba5a0566ace987f6ddd22d2f52b8840522a0fe Mon Sep 17 00:00:00 2001 From: BruceChen Date: Thu, 24 Mar 2022 20:48:40 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=B8=BAprev=E6=8C=87=E9=92=88=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=88=9D=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + main.cpp | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 9ed92a0..7cef28d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build GNUmakefile +.cache \ No newline at end of file diff --git a/main.cpp b/main.cpp index 75ae183..de7e3cd 100644 --- a/main.cpp +++ b/main.cpp @@ -6,16 +6,14 @@ struct Node { /* Q: 这两个指针会造成什么问题? A: 产生了环形引用,导致无法解构。 */ std::unique_ptr next; - struct Node* prev; + struct Node* prev = nullptr; // 如果能改成 unique_ptr 就更好了! int value; /* Q: 这个构造函数有什么可以改进的? A: 添加 explicit 避免隐式转换。 */ - explicit Node(int val) { - value = val; - } + explicit Node(int val) : value(val) {} void insert(int val) { auto node = std::make_unique(val);