作业地址
个人作业主页
修改 main.cpp,改良其中的双链表类 List:
避免函数参数不必要的拷贝 5 分
修复智能指针造成的问题 10 分
改用 unique_ptr 10 分
实现拷贝构造函数为深拷贝 15 分
说明为什么可以删除拷贝赋值函数 5 分
改进 Node 的构造函数 5 分
并通过 main() 函数中的基本测试。
如果你把 List 改成了基于迭代器的,或是作为模板 List: 只要是在 满足作业要求的基础 上,这是件好事! 老师会酌情加分,视为“独特的创新点”,但最多不超过 20 分。
思路基于shared_ptr和weak_ptr去实现模板类:
首先源代码中Node节点的前驱和后继均为shared_ptr,这是一个会产生循环引用的典型情况,修改原则:拥有所属权的对象设置为shared_ptr,没有所属权的改为weak_ptr。在链表中,当前节点对下一个节点拥有所属权,对上一节点无所属权,对节点的定义进行修改如下(个人认为改成unique_ptr意义不大):
templatestruct Node { std::shared_ptr next; std::weak_ptr prev; T value; // 防止隐式类型转化 explicit Node(T val) : value(val) {} void insert(T val) { auto node = std::make_shared (val); node->next = next; node->prev = prev; if (!prev.expired()) prev.lock()->next = node; if (next) next->prev = node; } void erase() { if (!prev.expired()) prev.lock()->next = next; if (next) next->prev = prev; } ~Node() { printf("~Node()n"); } };
修改List类(也改成模板类),改成浅拷贝很容易,然后在这个类里面,原来的代码删除了拷贝赋值函数,但是List a = {}仍然可以成功运行,是由于编译器自动调用了移动赋值函数,相当于List a = List({}),右边是一个临时对象,会当成右值引用,然后调用移动赋值函数。
templatestruct List { std::shared_ptr > head; List() = default; List(List const &other) { printf("List 被拷贝!n"); //head = other.head; // 这是浅拷贝! // 请实现拷贝构造函数为 **深拷贝** auto other_cur = other.head; head = std::make_shared >(other_cur->value); other_cur = other_cur->next; std::shared_ptr > cur = head; while (other_cur) { auto tmp = std::make_shared >(other_cur->value); cur->next = tmp; tmp->prev = cur; cur = tmp; other_cur = other_cur->next; } } List &operator=(List const &) = delete; // 为什么删除拷贝赋值函数也不出错 // 编译器会自动调用移动赋值函数 List(List &&) = default; List &operator=(List &&) = default; Node *front() const { return head.get(); } T 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; } };
当然print函数也要改成模板函数:
templatevoid print(const List & lst) { // 有什么值得改进的? printf("["); for (auto curr = lst.front(); curr; curr = curr->next.get()) { // printf(" %d", curr->value); std::cout << " " << curr->value; } printf(" ]n"); }
改成基于迭代器这点没看太明白,求教。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)