[2018年5月12号]C++ primer 课后练习第十三章 拷贝控制

类似于破窗理论,在前一周进行搬家之后休息了两天,感觉又将一部分的自己放到了舒适区,又在拷贝控制这章最后比较难的部分,感觉到自己的懈怠,在此提醒自己,希望可以对自己有一个警醒,不积跬步无以至千里~

13.49

    String(String &&s):begin(std::move(s.begin)),end(std::move(s.end)){
        begin = end = nullptr;
    }

    String& operator=(String &&s) {
        if(this != &s){
            this->begin = std::move(s.begin);
            this->end = std::move(s.end);
            s.begin = s.end = nullptr;
        }
        return *this;
    }

    StrVec(StrVec&& s):emlemnts(std::move(s.emlemnts)), first_free(std::move(s.first_free)), cap(std::move(s.cap)){
        s.emlemnts = s.first_free = s.cap = nullptr;
    };

    StrVec& operator=(StrVec&&s){
        if(this != &s){
            free();
            this->emlemnts = s.emlemnts;
            this->first_free = s.first_free;
            this->cap = s.cap;
            s.emlemnts = s.first_free = s.cap = nullptr;
        }
        return *this;
    };

    Message(Message&& m):contents(std::move(m.contents)) {
        folders = std::move(m.folders);
        for(auto f: folders){
            f->remMsg(&m);
            f->addMsg(this);
        }
        m.folders.clear();
    };
    Message& operator=(Message&& m){
        if(this != &m){
            folders = std::move(m.folders);
            for (auto f : folders) {
                f->remMsg(&m);
                f->addMsg(this);
            }
            m.folders.clear();
        }
        return *this;
    };

13.50


增加移动拷贝构造函数后,当前所有操作都是使用移动拷贝构造函数

13.51

clone函数返回的是一个临时变量,在unique_ptr初始化时候使用了移动构造函数,将临时变量移动到了当前unique_ptr上所以说合法并且能正确的工作

13.52

hp通过赋值运算符拷贝了hp2的数据

hp通过移动赋值运算符获得了hp2的数据,之后的hp2将是未定义的,不能使用,在移动赋值运算符执行过程中,临时变量rhs由于HasPtr拥有移动拷贝构造函数,所以根据左值拷贝构造,右值移动拷贝构造的原则,rhs将通过移动拷贝构造函数获得hp2的值,并且交给了hp,

总的来说hp = std::move(hp2)一共执行了1次移动拷贝构造函数和一次移动赋值运算符

13.53

    HasPtr& operator = (HasPtr& has){
        if (this != &has) {
            auto newps = new string(*has.ps);
            delete ps;
            ps = newps;
            i = has.i;
        }
        return *this;
    }
    HasPtr& operator = (HasPtr&& has) {
        //auto newps = new string(*has.ps);
        if (this != &has) {
            delete ps;
            ps = std::move(has.ps);
            i = std::move(has.i);
            use_count = std::move(has.use_count);
        }
        return *this;
    }

13.53

    HasPtr& operator = (HasPtr& has){
        if (this != &has) {
            auto newps = new string(*has.ps);
            delete ps;
            ps = newps;
            i = has.i;
        }
        return *this;
    }
    HasPtr& operator = (HasPtr&& has) {
        //auto newps = new string(*has.ps);
        if (this != &has) {
            delete ps;
            ps = std::move(has.ps);
            i = std::move(has.i);
            use_count = std::move(has.use_count);
        }
        return *this;
    } 

底层是由swap实现的,赋值运算符传入的是临时变量,在生成临时变量时会进行一次拷贝构造函数或移动拷贝构造函数操作,所以会有效率的影响,指定传入的左值引用和右值引用后,效率会提升

13.54

这个拷贝并交换运算符,半天没看懂,在查询网络大家的解题后,应该是指的最初的版本传入临时变量,并执行swap函数的赋值运算符版本,在同时存在移动赋值运算符和最初版本的情况下,赋值运算符的执行情况

    HasPtr& operator = (HasPtr has) {
        //auto newps = new string(*has.ps);
        cout << "operator = (HasPtr has)" << endl;
        if (this != &has) {
            swap(*this, has);
        }
        return *this;
    }
    HasPtr& operator = (HasPtr&& has) {
        cout << "operator = (HasPtr &&has)" << endl;
        //auto newps = new string(*has.ps);
        if (this != &has) {
            delete ps;
            ps = std::move(has.ps);
            i = std::move(has.i);
            use_count = std::move(has.use_count);
        }
        return *this;
    } 

结果如下


使用的拷贝并交换运算符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值