C++高性能编程hw02(RAII)

C++高性能编程hw02(RAII),第1张

C++高性能编程hw02(RAII) HW01

作业地址
个人作业主页

作业描述

修改 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意义不大):

template 
struct 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({}),右边是一个临时对象,会当成右值引用,然后调用移动赋值函数。

template 
struct 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函数也要改成模板函数:

template 
void 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");
}

改成基于迭代器这点没看太明白,求教。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5711158.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存