From 4e620d446068b76afe9e106c53b1ee7ed51b77fb Mon Sep 17 00:00:00 2001 From: xiao-ming-hub <3154802372@qq.com> Date: Wed, 18 Jan 2023 15:08:40 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.cpp | 57 +++++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/main.cpp b/main.cpp index dc25c6b..b4c5b0e 100644 --- a/main.cpp +++ b/main.cpp @@ -3,33 +3,23 @@ #include struct Node { - // 这两个指针会造成什么问题?请修复 - std::shared_ptr next; - std::shared_ptr prev; + // 这两个指针会造成什么问题?请修复。 + std::unique_ptr next; + Node *prev; // 如果能改成 unique_ptr 就更好了! int value; // 这个构造函数有什么可以改进的? - Node(int val) { - value = val; - } + Node(int val): value(val) {} void insert(int val) { - auto node = std::make_shared(val); - node->next = next; - node->prev = prev; - if (prev) - prev->next = node; - if (next) - next->prev = node; + value = val; } void erase() { - if (prev) - prev->next = next; - if (next) - next->prev = prev; + if (next) next->prev = prev; + if (prev) prev->next = std::move(next); } ~Node() { @@ -38,17 +28,25 @@ struct Node { }; struct List { - std::shared_ptr head; + std::unique_ptr head; List() = default; List(List const &other) { printf("List 被拷贝!\n"); - head = other.head; // 这是浅拷贝! // 请实现拷贝构造函数为 **深拷贝** + if (other.head == nullptr) return; // 空链表 + Node *it = other.front(), *tail; + head = std::make_unique(it->value); + for (it = it->next.get(), tail = head.get(); it; it = it->next.get()) { + tail->next = std::make_unique(it->value); + tail->next->prev = tail; + tail = tail->next.get(); + } } - List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? + List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? + // 因为编译器会用“解构函数+拷贝构造”代替拷贝赋值。 List(List &&) = default; List &operator=(List &&) = default; @@ -58,17 +56,18 @@ struct List { } int pop_front() { + if (head == nullptr) return 0x114154; int ret = head->value; - head = head->next; + head = std::move(head->next); return ret; } void push_front(int value) { - auto node = std::make_shared(value); - node->next = head; + auto node = new Node(value); if (head) head->prev = node; - head = node; + node->next = std::move(head); + head = std::unique_ptr(node); } Node *at(size_t index) const { @@ -80,12 +79,10 @@ struct List { } }; -void print(List lst) { // 有什么值得改进的? - printf("["); - for (auto curr = lst.front(); curr; curr = curr->next.get()) { - printf(" %d", curr->value); - } - printf(" ]\n"); +void print(List const &lst) { // 有什么值得改进的? + for (auto curr = lst.front(); curr; curr = curr->next.get()) + printf("this: %p prev: %p next: %p value: %d\n", + curr, curr->prev, curr->next.get(), curr->value); } int main() { From 1ee2aa498eda50b8348b504e040de25832e1cdb7 Mon Sep 17 00:00:00 2001 From: xiao-ming-hub <3154802372@qq.com> Date: Wed, 18 Jan 2023 15:28:12 +0800 Subject: [PATCH 2/4] support template --- main.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/main.cpp b/main.cpp index b4c5b0e..21b1125 100644 --- a/main.cpp +++ b/main.cpp @@ -2,18 +2,18 @@ #include #include -struct Node { +template struct Node { // 这两个指针会造成什么问题?请修复。 std::unique_ptr next; Node *prev; // 如果能改成 unique_ptr 就更好了! - int value; + Tp value; // 这个构造函数有什么可以改进的? - Node(int val): value(val) {} + Node(Tp val): value(val) {} - void insert(int val) { + void insert(Tp val) { value = val; } @@ -27,8 +27,8 @@ struct Node { } }; -struct List { - std::unique_ptr head; +template struct List { + std::unique_ptr> head; List() = default; @@ -36,10 +36,10 @@ struct List { printf("List 被拷贝!\n"); // 请实现拷贝构造函数为 **深拷贝** if (other.head == nullptr) return; // 空链表 - Node *it = other.front(), *tail; - head = std::make_unique(it->value); + Node *it = other.front(), *tail; + head = std::make_unique>(it->value); for (it = it->next.get(), tail = head.get(); it; it = it->next.get()) { - tail->next = std::make_unique(it->value); + tail->next = std::make_unique>(it->value); tail->next->prev = tail; tail = tail->next.get(); } @@ -51,7 +51,7 @@ struct List { List(List &&) = default; List &operator=(List &&) = default; - Node *front() const { + Node *front() const { return head.get(); } @@ -63,14 +63,14 @@ struct List { } void push_front(int value) { - auto node = new Node(value); + auto node = new Node(value); if (head) head->prev = node; node->next = std::move(head); - head = std::unique_ptr(node); + head = std::unique_ptr>(node); } - Node *at(size_t index) const { + Node *at(size_t index) const { auto curr = front(); for (size_t i = 0; i < index; i++) { curr = curr->next.get(); @@ -79,14 +79,14 @@ struct List { } }; -void print(List const &lst) { // 有什么值得改进的? +template void print(List const &lst) { // 有什么值得改进的? for (auto curr = lst.front(); curr; curr = curr->next.get()) - printf("this: %p prev: %p next: %p value: %d\n", + printf("this: %p prev: %p next: %p value: %lf\n", curr, curr->prev, curr->next.get(), curr->value); } int main() { - List a; + List a; a.push_front(7); a.push_front(5); @@ -102,7 +102,7 @@ int main() { print(a); // [ 1 4 2 8 5 7 ] - List b = a; + List b = a; a.at(3)->erase(); From fc5db27e31e9bda87d65a82d57a10645b1b2d2c9 Mon Sep 17 00:00:00 2001 From: xiao-ming-hub <3154802372@qq.com> Date: Wed, 18 Jan 2023 16:32:48 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E8=BF=AD=E4=BB=A3=E5=99=A8=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20=E8=B0=83=E6=95=B4=E7=B1=BB=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E9=A1=BA=E5=BA=8F=20=E5=88=A0=E7=82=B9?= =?UTF-8?q?=E7=A9=BA=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.cpp | 61 +++++++++++++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/main.cpp b/main.cpp index 21b1125..8af81ce 100644 --- a/main.cpp +++ b/main.cpp @@ -1,39 +1,28 @@ /* 基于智能指针实现双向链表 */ -#include +#include #include template struct Node { - // 这两个指针会造成什么问题?请修复。 std::unique_ptr next; Node *prev; - // 如果能改成 unique_ptr 就更好了! - Tp value; - // 这个构造函数有什么可以改进的? Node(Tp val): value(val) {} + ~Node() { std::clog << "~Node(" << value << ")\n"; } - void insert(Tp val) { - value = val; - } - + void insert(Tp val) { value = val; } void erase() { if (next) next->prev = prev; if (prev) prev->next = std::move(next); } - - ~Node() { - printf("~Node()\n"); // 应输出多少次?为什么少了? - } }; template struct List { std::unique_ptr> head; List() = default; - List(List const &other) { - printf("List 被拷贝!\n"); + std::clog << "List 被拷贝!\n"; // 请实现拷贝构造函数为 **深拷贝** if (other.head == nullptr) return; // 空链表 Node *it = other.front(), *tail; @@ -44,24 +33,32 @@ template struct List { tail = tail->next.get(); } } - List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? // 因为编译器会用“解构函数+拷贝构造”代替拷贝赋值。 - List(List &&) = default; List &operator=(List &&) = default; - Node *front() const { - return head.get(); - } - + struct iterator { + Node *node; + iterator(Node *p): node(p) {} + + Tp operator*() { return node->value; } + iterator operator++() { return node = node->next.get(); } + iterator operator--() { return node = node->prev; } + bool operator==(iterator const &other) { return node == other.node; } + bool operator!=(iterator const &other) { return node != other.node; } + }; + iterator begin() const { return iterator(head.get()); } + iterator end() const { return iterator(nullptr); } + + Node *front() const { return head.get(); } + bool empty() const { return !(head); } int pop_front() { if (head == nullptr) return 0x114154; int ret = head->value; head = std::move(head->next); return ret; } - void push_front(int value) { auto node = new Node(value); if (head) @@ -69,7 +66,6 @@ template struct List { node->next = std::move(head); head = std::unique_ptr>(node); } - Node *at(size_t index) const { auto curr = front(); for (size_t i = 0; i < index; i++) { @@ -79,15 +75,16 @@ template struct List { } }; -template void print(List const &lst) { // 有什么值得改进的? - for (auto curr = lst.front(); curr; curr = curr->next.get()) - printf("this: %p prev: %p next: %p value: %lf\n", - curr, curr->prev, curr->next.get(), curr->value); +template +std::ostream &operator<<(std::ostream &os, List const &l) { + for (os << '['; Tp x : l) os << x << ", "; + os << (l.empty() ? "]" : "\b\b]"); + return os; } int main() { +#define print(l) std::cout << l << '\n'; List a; - a.push_front(7); a.push_front(5); a.push_front(8); @@ -95,22 +92,14 @@ int main() { a.push_front(9); a.push_front(4); a.push_front(1); - print(a); // [ 1 4 9 2 8 5 7 ] - a.at(2)->erase(); - print(a); // [ 1 4 2 8 5 7 ] - List b = a; - a.at(3)->erase(); - print(a); // [ 1 4 2 5 7 ] print(b); // [ 1 4 2 8 5 7 ] - b = {}; a = {}; - return 0; } From f7466ca9e01d3204a46f341538ef5ad27ee174a1 Mon Sep 17 00:00:00 2001 From: xiao-ming-hub <3154802372@qq.com> Date: Wed, 18 Jan 2023 17:32:57 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BA=86=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 写完后发现代码几乎和拷贝构造函数一样,于是就想着把它们合并起来。结 果发现构造函数不会写了。cppreference 说 std::ranges::range 可以实 现这个需求,但我的库不支持。我想把那一个函数写成模板(也是不会写) 所以多出来了一个参数,有点臃肿。 编译时会警告,我给 CMakeLists.txt 加上 target_compile_options( main PUBLIC -std=c++20) 还是报(强迫症)。 --- main.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/main.cpp b/main.cpp index 8af81ce..25b3f60 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ /* 基于智能指针实现双向链表 */ #include #include +#include template struct Node { std::unique_ptr next; @@ -17,18 +18,17 @@ template struct Node { } }; -template struct List { +template > struct List { std::unique_ptr> head; List() = default; - List(List const &other) { - std::clog << "List 被拷贝!\n"; - // 请实现拷贝构造函数为 **深拷贝** - if (other.head == nullptr) return; // 空链表 - Node *it = other.front(), *tail; - head = std::make_unique>(it->value); - for (it = it->next.get(), tail = head.get(); it; it = it->next.get()) { - tail->next = std::make_unique>(it->value); + List(Init const &range) { + if (range.begin() == range.end()) return; + Node *tail; + auto it = range.begin(); + head = std::make_unique>(*it); + for (++it, tail = head.get(); it != range.end(); ++it) { + tail->next = std::make_unique>(*it); tail->next->prev = tail; tail = tail->next.get(); } @@ -75,8 +75,8 @@ template struct List { } }; -template -std::ostream &operator<<(std::ostream &os, List const &l) { +template +std::ostream &operator<<(std::ostream &os, List const &l) { for (os << '['; Tp x : l) os << x << ", "; os << (l.empty() ? "]" : "\b\b]"); return os; @@ -84,18 +84,11 @@ std::ostream &operator<<(std::ostream &os, List const &l) { int main() { #define print(l) std::cout << l << '\n'; - List a; - a.push_front(7); - a.push_front(5); - a.push_front(8); - a.push_front(2); - a.push_front(9); - a.push_front(4); - a.push_front(1); + List a = {1, 4, 9, 2, 8, 5, 7}; print(a); // [ 1 4 9 2 8 5 7 ] a.at(2)->erase(); print(a); // [ 1 4 2 8 5 7 ] - List b = a; + List> b = a; a.at(3)->erase(); print(a); // [ 1 4 2 5 7 ] print(b); // [ 1 4 2 8 5 7 ]