diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..38f7d0a --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,20 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "compilerPath": "C:\\Program Files\\mingw64\\bin\\gcc.exe", + "cStandard": "c23", + "cppStandard": "c++17", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5c7247b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6848ac3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,77 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "optional": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "cfenv": "cpp", + "map": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "ctime": "cpp", + "ratio": "cpp", + "iomanip": "cpp", + "bitset": "cpp", + "variant": "cpp", + "typeindex": "cpp", + "charconv": "cpp", + "cinttypes": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "cstring": "cpp", + "cuchar": "cpp", + "forward_list": "cpp", + "list": "cpp", + "unordered_set": "cpp", + "functional": "cpp", + "iterator": "cpp", + "numeric": "cpp", + "random": "cpp", + "regex": "cpp", + "set": "cpp", + "future": "cpp", + "mutex": "cpp", + "scoped_allocator": "cpp", + "shared_mutex": "cpp", + "thread": "cpp", + "valarray": "cpp" + }, + "C_Cpp.errorSquiggles": "disabled" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..6db2949 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,29 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++.exe build active file", + "command": "C:\\Program Files\\mingw64\\bin\\g++.exe", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}\\${fileBasenameNoExtension}.exe", + "-std=c++2a" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "compiler: \"C:\\Program Files\\mingw64\\bin\\g++.exe\"" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 2735d0d..8b2a38a 100644 --- a/README.md +++ b/README.md @@ -26,17 +26,17 @@ 修改 main.cpp,改良其中的双链表类 `List`: -- 避免函数参数不必要的拷贝 5 分 -- 修复智能指针造成的问题 10 分 +- 避免函数参数不必要的拷贝 5 分 done! +- 修复智能指针造成的问题 10 分 - 改用 `unique_ptr` 10 分 - 实现拷贝构造函数为深拷贝 15 分 -- 说明为什么可以删除拷贝赋值函数 5 分 +- 说明为什么可以删除拷贝赋值函数 5 分 done! - 改进 `Node` 的构造函数 5 分 并通过 `main()` 函数中的基本测试。 ## 关于内卷 -如果你把 List 改成了基于迭代器的,或是作为模板 `List`: +如果你把 List 改成了基于迭代器的,或是作为模板 `List`: done! 只要是在 **满足作业要求的基础** 上,这是件好事! -老师会酌情加分,视为“独特的创新点”,但最多不超过 20 分。 +老师会酌情加分,视为“独特的创新点”,但最多不超过 20 分。 \ No newline at end of file diff --git a/main.cpp b/main.cpp index dc25c6b..5253fea 100644 --- a/main.cpp +++ b/main.cpp @@ -1,119 +1,155 @@ +// ConsoleApplication3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include /* 基于智能指针实现双向链表 */ #include #include - +#include struct Node { - // 这两个指针会造成什么问题?请修复 - std::shared_ptr next; - std::shared_ptr prev; - // 如果能改成 unique_ptr 就更好了! - - int value; - - // 这个构造函数有什么可以改进的? - 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; - } - - void erase() { - if (prev) - prev->next = next; - if (next) - next->prev = prev; - } - - ~Node() { - printf("~Node()\n"); // 应输出多少次?为什么少了? - } + // 这两个指针会造成什么问题?请修复 done + std::unique_ptr next; + Node* prev; + int value; + + // 这个构造函数有什么可以改进的? done + Node() = default; + + Node(int val, Node* prev1 = nullptr) { + value = val; + std::unique_ptr next = std::make_unique(); + prev = prev1; + } + + void insert(int val) { + auto node = std::make_unique(val); + node->next = std::move(next); + node->prev = prev; + if (prev) + prev->next = std::move(node); + prev = nullptr; + if (next) + next->prev = node.get(); + next->prev = nullptr; + } + + void erase() { + if (next) + next->prev = prev; + + if (prev) + prev->next = std::move(next); + prev = nullptr; + } + + ~Node() { + // printf("~Node()\n"); // 应输出多少次?为什么少了? + } }; +template struct List { - std::shared_ptr head; - - List() = default; - - List(List const &other) { - printf("List 被拷贝!\n"); - head = other.head; // 这是浅拷贝! - // 请实现拷贝构造函数为 **深拷贝** - } - - List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? - - List(List &&) = default; - List &operator=(List &&) = default; - - Node *front() const { - return head.get(); - } - - int pop_front() { - int ret = head->value; - head = head->next; - return ret; - } - - void push_front(int value) { - auto node = std::make_shared(value); - node->next = head; - if (head) - head->prev = node; - head = node; - } - - Node *at(size_t index) const { - auto curr = front(); - for (size_t i = 0; i < index; i++) { - curr = curr->next.get(); - } - return curr; - } + std::unique_ptr head; + + List() = default; + + List(List const &other) { + printf("List 被拷贝!\n"); + + // head = other.head; // 这是浅拷贝! + // 请实现拷贝构造函数为 **深拷贝** + head = std::make_unique(other.head->value); + + if ((!other.head->next.get()) && (!other.head->prev)) { + std::cout << "ok" << std::endl; + return; + } + else { + auto now_ptr = other.head->next.get(); + auto prev_ptr = head.get(); + while (now_ptr) { + auto list_ptr = std::make_unique(now_ptr->value, prev_ptr); + prev_ptr->next = std::move(list_ptr); + std::cout << prev_ptr->value << std::endl; + + now_ptr = now_ptr->next.get(); + prev_ptr = prev_ptr->next.get(); + } + } + } + + List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错? done + + List(List &&) = default; + List &operator=(List &&) = default; + + Node *front() const { + return head.get(); + } + + T pop_front() { + T ret = head->value; + head = head->next; + return ret; + } + + void push_front(T value) { + auto node = std::make_unique(value); + if (head) + head->prev = node.get(); + node->next = std::move(head); + head = std::move(node); + } + + Node *at(size_t index) const { + auto curr = front(); + for (size_t i = 0; i < index; i++) { + curr = curr->next.get(); + } + return curr; + } }; - -void print(List lst) { // 有什么值得改进的? - printf("["); - for (auto curr = lst.front(); curr; curr = curr->next.get()) { - printf(" %d", curr->value); - } - printf(" ]\n"); +template +void print(const List &lst) { // 有什么值得改进的? done + printf("["); + for (auto curr = lst.front(); curr; curr = curr->next.get()) { + printf(" %d", curr->value); + } + printf(" ]\n"); } int main() { - List a; + 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); + + print(a); // [ 1 4 9 2 8 5 7 ] + // std::cout << a.at(0) << std::endl; + // std::cout << a.at(1)->prev << std::endl; - 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); + // std::cout << a.at(1) << std::endl; + // std::cout << a.at(0)->next.get() << std::endl; - print(a); // [ 1 4 9 2 8 5 7 ] - a.at(2)->erase(); + a.at(2)->erase(); - print(a); // [ 1 4 2 8 5 7 ] + print(a); // [ 1 4 2 8 5 7 ] - List b = a; + List b = a; - a.at(3)->erase(); + a.at(3)->erase(); - print(a); // [ 1 4 2 5 7 ] - print(b); // [ 1 4 2 8 5 7 ] + print(a); // [ 1 4 2 5 7 ] + print(b); // [ 1 4 2 8 5 7 ] - b = {}; - a = {}; + // b = {}; + // a = {}; - return 0; + return 0; } diff --git a/main.exe b/main.exe new file mode 100644 index 0000000..319138c Binary files /dev/null and b/main.exe differ