美文网首页
c++primer 13.45-13.58

c++primer 13.45-13.58

作者: 青吟乐 | 来源:发表于2019-06-09 00:01 被阅读0次

    13.45
    平时引用是左值引用,当时用&&的时候就是右值引用比如
    左值引用:

    int a = 2;
    int &p = a;
    

    右值引用:

    int &&p = 3;
    int &&q = p;
    

    左值持久,右值短暂,左值具有持久的状态,右值要么是字面值常量,要么是在表达式求值的过程中创建的临时对象(没有其他用户进行绑定且要被销毁):使用右值引用的代码可以自由的接管所引用的对象的资源
    13.46
    f()返回值类型是int,属于使用f()后才有的临时变量,使用&&
    &
    &
    &&
    13.47

    String::String(const String&s){
        std::cout<<"拷贝构造函数"<<std::endl;
        auto newStr = alloc_n_copy(s.elements,s.first_free);
        elements = newStr.first;
        first_free = newStr.second;
    }
    
    String& String::operator=(const String&a){
        std::cout<<"拷贝赋值运算符"<<std::endl;
        auto newc = alloc_n_copy(a.elements,a.first_free);
        free();
        elements = newc.first;
        first_free = newc.second;
        return *this;
    }
    

    13.48

    提示我 image.png
    不知道为啥申请不到空间,我再看看
    #include <iostream>
    #include"String.h"
    #include<vector>
    using namespace std;
    
    int main()
    {
        std::vector<String> vec;
        String s1("xxx");
        String s2 = s1;
        vec.push_back(s1);
        vec.push_back(s2);
    
        return 0;
    }
    
    

    13.49
    Message类

    //从本message移动Folder指针
    void Message::move_Folders(Message *m){
        folders = std::move(m->folders);
        for(auto v:folders){
            v->remMsg(m);
            v->addMsg(this);
        }
        m->folders.clear();
    }
    //移动构造函数
    Message::(Message &&m){
        contents = m.contents;
        move_Folders(&m);
    }
    //移动赋值运算符
    Message& Message::operator=(Message &&rhs){
        if(this!=&rhs){
            remove_from_Folders();
            contents = std::move(rhs.contents);
            move_Folders(&rhs);
        }
        return *this;
    }
    

    StrVec类

    //移动构造函数
    StrVec::StrVec(StrVec &&s) noexcept:elements(s.elements),first_free(s.first_free),cap(s.cap){
        //另s进入这样的状态-----对其运行析构函数是安全的
        s.elements = s.first_free = s.cap = nullptr;
    }
    //移动赋值运算符
    StrVec &StrVec::operator=(StrVec &&rhs) noexcept{
        //首先检测自身赋值
        if(this != &rhs){
            free();                                 //释放已有元素
            elements = rhs.elements;                //从rhs接管资源
            first_free = rhs.first_free;
            cap = rhs.cap;
            //将rhs置于可析构的状态
            rhs.elements = rhs.first_free = rhs.cap = nullptr;
        }
        return *this;
    }
    

    String类

    //移动构造函数
    String::String(String &&s) noexcept{
        std::cout<<"移动构造函数"<<std::endl;
        elements = s.elements;
        first_free = s.first_free;
        s.elements = s.first_free = nullptr;
    
    }
    //移动赋值运算符
    String &String::operator=(String &&rhs) noexcept{
        std::cout<<"移动赋值运算符"<<std::endl;
        if(this!=&rhs){
            free();
            elements = rhs.elements;
            first_free = rhs.first_free;
            rhs.elements = rhs.first_free = nullptr;
        }
        return *this;
    }
    

    13.50
    参考cpp答案

    #include <iostream>
    #include"String.h"
    #include<vector>
    using namespace std;
    
    String R(){
    std::vector<String> vec;
        String s1("s");//默认构造函数
        vec.push_back(s1);//拷贝构造函数
        return s1;//临时量,移动构造函数
    }
    int main()
    {
        String s=R();//移动构造函数
        return 0;
    }
    
    

    13.51
    这里使用了移动构造函数,因为new int(p)是一个产生临时变量的表达式,所以它是一个右值,所以这里可以使用移动构造函数
    13.52
    hp2是左值,实用拷贝构造函数
    std::move(hp2);就是使用移动操作啦std::move(hp2);是右值,可以使用移动构造函数
    13.53
    缺少移动操作,书上版本

        //移动构造函数
        HasPtr(HasPtr &&p) noexcept{
            ps = p.ps;
            i = p.i;
            p.ps = 0;
        }
        //赋值运算符既算是移动赋值运算符也算是拷贝赋值运算符
        HasPtr& operator=(HasPtr rhs){
            swap(*this,rhs);
            return *this;
        }
    

    13.54
    C:\wook_tool\MyCppSpace\primer_13_3\main.cpp|12|error: ambiguous overload for 'operator=' (operand types are 'HasPtr' and 'std::remove_reference<HasPtr&>::type {aka HasPtr}')|
    13.55

    void StrVec::push_back(std::string &&s){
        chk_n_alloc();                      //确保有空间容纳新的元素
        alloc.construct(first_free++,std::move(s));    //在first_free指向的元素中构造s的副本
    }
    

    13.56
    ret是左值对象,是一直调用当前的sort,递归
    13.57
    Foo(*this)只会产生临时对象,就会调用&&版本的sort
    13.58

    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    using std::vector; using std::sort;
    
    class Foo
    {
    public:
        Foo sorted() && ;
        Foo sorted() const &;
    private:
        vector<int> data;
    };
    
    Foo Foo::sorted() && {
        sort(data.begin(), data.end());
        std::cout << "&&" << std::endl; // debug
        return *this;
    }
    
    Foo Foo::sorted() const &
    {
        //    Foo ret(*this);
        //    sort(ret.data.begin(), ret.data.end());
        //    return ret;
    
        std::cout << "const &" << std::endl; // debug
    
          //  Foo ret(*this);
          //  ret.sorted();     // Exercise 13.56
           // return ret;
    
        return Foo(*this).sorted(); // Exercise 13.57
    }
    
    int main()
    {
        Foo().sorted(); // call "&&"
        Foo f;
        f.sorted(); // call "const &"
    }
    

    相关文章

      网友评论

          本文标题:c++primer 13.45-13.58

          本文链接:https://www.haomeiwen.com/subject/ufjwxctx.html