栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/714511.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号