diff --git a/main.cpp b/main.cpp index dc25c6b..9f2ac9f 100644 --- a/main.cpp +++ b/main.cpp @@ -4,51 +4,89 @@ struct Node { // 这两个指针会造成什么问题?请修复 - std::shared_ptr next; - std::shared_ptr prev; + // 当两个都是shared_ptr时 如果node1.next = node2, node2.prev = node1的话, + // 当我们想recycle这两个node,node1 = nptr; node2 = nptr. + // 由于node2.prev还指向node1,并且node1的next还只向node2,那么就会出现释放不了的清空 + // 所以最好一个是unique--省去了维护ref count的开销,另一个可以是原生pointer或者weak。 + // 我觉得这样declare attributes的好处还有维护爷爷,爸爸,儿子的关系。 + // 始终是你的儿子是unique,然后你儿子对自己不是unique,你儿子对你孙子是unique。 + // 保证了同时只有一个指向unique的东西存在。 + std::unique_ptr next; + Node* prev; // 如果能改成 unique_ptr 就更好了! int value; - // 这个构造函数有什么可以改进的? - Node(int val) { - value = val; + // 这个构造函数有什么可以改进的?use list members to avoid direct assigning + Node(int val) : value(val) { } - + + // 由于next是unique,那么当我插入的时候,我要全权将next的所有权给当前的node 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; + auto node = std::make_unique(val); + if (this->next) { //当前node的下一个node的prev应该指向新建的node + this->next->prev = node.get(); + } + node->next = std::move(this->next); //将我原本next的所有权给当前插入的node + if (this->prev) { + node->prev = this; + } + this->next = std::move(node); // 将新建node的所有全给我现在的这个node + // if (prev) + // prev->next = node; + // if (next) + // next->prev = node; } void erase() { - if (prev) - prev->next = next; + // 这里的顺序尤为重要,之前因为先move了next的所有权导致了后access next->prev造成segfault if (next) - next->prev = prev; + next->prev = prev; + + if (prev) + prev->next = std::move(this->next); + } ~Node() { - printf("~Node()\n"); // 应输出多少次?为什么少了? + printf("~Node(%d)\n", value); // 应输出多少次?为什么少了?因为shared_ptr带来的循环指针导致总是有一个ref count让shared_ptr不能自动回收 } }; struct List { - std::shared_ptr head; + std::unique_ptr head; List() = default; + // List(List const &other) { + // printf("List 被拷贝!\n"); + // head = other.head; // 这是浅拷贝! + // // 请实现拷贝构造函数为 **深拷贝** + // } + List(List const &other) { - printf("List 被拷贝!\n"); - head = other.head; // 这是浅拷贝! - // 请实现拷贝构造函数为 **深拷贝** + printf("深拷贝\n"); + // 我第一想法是把other.head的所有权给this,但是需求应该不是这样 + if (other.head) { + head = std::make_unique(other.head->value); + //直接other.head access是不行的,因为unique_ptr, 所以用.get()获取本体 + Node* curr_src = other.head.get(); + + // 然后获取当前需要被copy into的内容 + Node* curr_dst = head.get(); + while (curr_src->next) { + curr_dst->next = std::make_unique(curr_src->next->value); + curr_dst->next->prev = curr_dst; // prev是本体指针,直接assign + curr_src = curr_src->next.get(); + curr_dst = curr_dst->next.get(); + } + + } + } List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? + // 因为实现了move operator overloading List(List &&) = default; List &operator=(List &&) = default; @@ -59,16 +97,17 @@ struct List { int pop_front() { 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 = std::make_unique(value); + if (head) - head->prev = node; - head = node; + head->prev = node.get(); + node->next = std::move(head); + head = std::move(node); } Node *at(size_t index) const { @@ -78,9 +117,13 @@ struct List { } return curr; } + + ~List() { + printf("Destructor of list is called\n"); + } }; -void print(List lst) { // 有什么值得改进的? +void print(const List& lst) { // 有什么值得改进的?加上&避免调用copy constructor printf("["); for (auto curr = lst.front(); curr; curr = curr->next.get()) { printf(" %d", curr->value); @@ -116,4 +159,4 @@ int main() { a = {}; return 0; -} +} \ No newline at end of file