Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 115 additions & 30 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,109 @@

struct Node {
// 这两个指针会造成什么问题?请修复
std::shared_ptr<Node> next;
std::shared_ptr<Node> prev;

// std::shared_ptr<Node> next;
// std::shared_ptr<Node> prev;

// 如果能改成 unique_ptr 就更好了!

// 改进1: 使用unique_ptr
std::unique_ptr<Node> next;
Node *prev;

int value;

// 这个构造函数有什么可以改进的?
Node(int val) {
value = val;
}

// Node(int val) {
// value = val;
// }

// 改进2:使用初始化列表
Node(int val) : value(val), next(nullptr), prev(nullptr) {}

// void insert(int val) {
// auto node = std::make_shared<Node>(val);
// node->next = next;
// node->prev = prev;
// if (prev)
// prev->next = node;
// if (next)
// next->prev = node;
// }

// 改进3: 修改插入逻辑,在当前节点后插入新值
void insert(int val) {
auto node = std::make_shared<Node>(val);
node->next = next;
node->prev = prev;
if (prev)
prev->next = node;
if (next)
next->prev = node;
auto node = std::make_unique<Node>(val);
node->prev = this;
if (next) {
next->prev = node.get();
node->next = std::move(next);
}
next = std::move(node);
}

// void erase() {
// if (prev)
// prev->next = next;
// if (next)
// next->prev = prev;
// }

// 改进4: 修改删除逻辑,删除当前节点的后继节点
void erase() {
if (prev)
prev->next = next;
if (next)
next->prev = prev;
if (next) {
if (next->next) {
next->next->prev = this;
}
next = std::move(next->next);
}
}

// 改进5: 修改析构函数,输出当前节点的值
~Node() {
printf("~Node()\n"); // 应输出多少次?为什么少了?
printf("~Node(%d)\n", value); // 应输出多少次?为什么少了?
}
};

struct List {
std::shared_ptr<Node> head;
// std::shared_ptr<Node> head;
// 修复1: 这里必须同步改为 unique_ptr,否则无法与 Node::next 兼容
std::unique_ptr<Node> head;

List() = default;

// List(List const &other) {
// printf("List 被拷贝!\n");
// head = other.head; // 这是浅拷贝!
// // 请实现拷贝构造函数为 **深拷贝**
// }

// 改进6:实现真正的深拷贝
List(List const &other) {
printf("List 被拷贝!\n");
head = other.head; // 这是浅拷贝!
// 请实现拷贝构造函数为 **深拷贝**
printf("List 被拷贝!进行深拷贝...\n");
if (!other.head) return;

// 拷贝第一个节点
head = std::make_unique<Node>(other.head->value);

Node *curr = head.get();
Node *other_curr = other.head->next.get();

// 顺序拷贝后续节点
while (other_curr) {
curr->next = std::make_unique<Node>(other_curr->value);
curr->next->prev = curr;
curr = curr->next.get();
other_curr = other_curr->next.get();
}
}

List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错?

// 问:为什么可以删除拷贝赋值函数?
// 答:因为在 main 中的 "List b = a;" 是初始化行为,调用的是拷贝构造函数而非赋值运算符。
// 如果没有类似 "b = a;" (在初始化之后赋值) 的代码,编译器就不需要拷贝赋值函数。

List(List &&) = default;
List &operator=(List &&) = default;

Expand All @@ -59,28 +116,52 @@ struct List {

int pop_front() {
int ret = head->value;
head = head->next;
// head = head->next;

// 改进7: 使用 std::move
head = std::move(head->next);
if (head) head->prev = nullptr;

return ret;
}

void push_front(int value) {
auto node = std::make_shared<Node>(value);
node->next = head;
if (head)
head->prev = node;
head = node;
// 修复2: 这里也应该统一使用 make_unique
auto node = std::make_unique<Node>(value);
// node->next = head;
// if (head)
// head->prev = node;
// head = node;

// 改进8: 使用 std::move
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++) {

// 改进9: 修改for循环终止条件
for (size_t i = 0; i < index && curr; i++) {
curr = curr->next.get();
}
return curr;
}
};

void print(List lst) { // 有什么值得改进的?
// void print(List lst) { // 有什么值得改进的?
// printf("[");
// for (auto curr = lst.front(); curr; curr = curr->next.get()) {
// printf(" %d", curr->value);
// }
// printf(" ]\n");
// }

// 改进10:使用 const & 避免按值传递导致的 List 拷贝
void print(List const &lst) {
printf("[");
for (auto curr = lst.front(); curr; curr = curr->next.get()) {
printf(" %d", curr->value);
Expand Down Expand Up @@ -115,5 +196,9 @@ int main() {
b = {};
a = {};

// 改进11:显式清空,触发析构输出
b = {};
a = {};

return 0;
}