zoukankan      html  css  js  c++  java
  • c++ 11学习笔记--右值引用和移动构造语义

    今天我决定尝试用另外一种方式来表达,任何新语法的的产生都是为了解决某个问题,所以今天先看问题。

    class myStr
    {
    protected:
        char* str_;
        
    public:
        myStr(void)                       // 默认的构造函数,什么也不做
        : str_(nullptr)
        {}
        
        myStr(const char* rhs)            // 普通赋值构造函数
        : str_(nullptr)
        {
            if (!rhs) return;
            str_ = new char[1024];
            strcpy(str_, rhs);
          //  cout << "Str constructor " << str_ << std::endl;
        }
        
        myStr(const myStr& rhs)             // 拷贝构造函数
        : str_(nullptr)
        {
            if (!rhs) return;
            str_ = new char[1024];
            strcpy(str_, rhs.str_);
          //  cout << "Str copy constructor " << str_ << std::endl;
        }
        
        myStr(myStr&& rhs)
        : str_(nullptr)
        {
            swap(rhs);
          //  std::cout << "Str move constructor " << str_ << std::endl;
        }
        
        ~myStr()                          // 析构函数
        {
            if (!str_) return;
          //  std::cout << "Str destructor " << str_ << std::endl;
            delete [] str_;
        }
        
        const myStr& operator=(myStr rhs)   // 赋值操作符重载
        {
            rhs.swap(*this);            // 使用copy-and-swap惯用法获得数据
            return (*this);             // 避免重复撰写operator=
        }
        
        void swap(myStr& rhs)             // 交换算法
        {
            std::swap(str_, rhs.str_);
        }
        
        operator char*(void) const
        {
            return str_;
        }
        
        myStr& operator+=(const char* rhs)
        {
            if (rhs) strcat(str_, rhs);
            return (*this);
        }
        
    //    friend myStr operator+(const myStr& x, const myStr& y)
    //    {
    //        return myStr(x) += y;
    //    }
        friend myStr operator+(const myStr& x, const myStr& y)
        {
            return std::move(myStr(x) += y);
    }

    执行下面的代码

    myStr ss("000");
        myStr s1("11111"), s2("22222"), s3("3333333"), s4("4444444");
        cout << std::endl;
        time_t timestamp1;
        time_t timestamp2;
        time_t timestamp3;
        
        const long long max = 30000000;
        time(&timestamp1);
    
        for (long long i = 0; i<max; i++) {
            ss = s1 + s2 + s3 + s4;
        }
         time(&timestamp2);
        
     timestamp3 = timestamp2 - timestamp1;

     下面的代码是唯一不同的实现,但是却带来30-40%的性能差距。

    /    friend myStr operator+(const myStr& x, const myStr& y)
    //    {
    //        return myStr(x) += y;
    //    }
        friend myStr operator+(const myStr& x, const myStr& y)
        {
            return std::move(myStr(x) += y);
    }

    再找一个例子

    class MemoryBlock
    {
    public:
        
        // 构造器(初始化资源)
        explicit MemoryBlock(size_t length)
        : _length(length)
        , _data(new int[length])
        {
            std::cout << "MemoryBlock constructor "  << std::endl;
        }
        
        // 析构器(释放资源)
        ~MemoryBlock()
        {
            if (_data != nullptr)
            {
                delete[] _data;
            }
            std::cout << "MemoryBlock destructor "  << std::endl;
        }
        
        // 拷贝构造器(实现拷贝语义:拷贝that)
        MemoryBlock(const MemoryBlock& that)
        // 拷贝that对象所拥有的资源
        : _length(that._length)
        , _data(new int[that._length])
        {
            std::copy(that._data, that._data + _length, _data);
            std::cout << "copy constructor "  << std::endl;
        }
        
        // 拷贝赋值运算符(实现拷贝语义:释放this + 拷贝that)
        MemoryBlock& operator=(const MemoryBlock& that)
        {
            if (this != &that)
            {
                // 释放自身的资源
                delete[] _data;
                
                // 拷贝that对象所拥有的资源
                _length = that._length;
                _data = new int[_length];
                std::copy(that._data, that._data + _length, _data);
            }
            return *this;
        }
        
        // 移动构造器(实现移动语义:移动that)
        MemoryBlock(MemoryBlock&& that)
        // 将自身的资源指针指向that对象所拥有的资源
        : _length(that._length)
        , _data(that._data)
        {
            // 将that对象原本指向该资源的指针设为空值
            that._data = nullptr;
            that._length = 0;
        }
        
        // 移动赋值运算符(实现移动语义:释放this + 移动that)
        MemoryBlock& operator=(MemoryBlock&& that)
        {
            if (this != &that)
            {
                // 释放自身的资源
                delete[] _data;
                
                // 将自身的资源指针指向that对象所拥有的资源
                _data = that._data;
                _length = that._length;
                
                // 将that对象原本指向该资源的指针设为空值
                that._data = nullptr;
                that._length = 0;
            }
            return *this;
        }
    private:
        size_t _length; // 资源的长度
        int* _data; // 指向资源的指针,代表资源本身
    };
    
    MemoryBlock f() { return MemoryBlock(50); }

    执行下面的代码

    const long long max = 100000;
        time_t timestamp1;
        time_t timestamp2;
        time_t timestamp3;
    
        time(&timestamp1);
        for (long long i = 0; i<max; i++)
        {
            MemoryBlock a = MemoryBlock(50);
    
            MemoryBlock c = std::move(a);
        }
        
        time(&timestamp2);
    timestamp3 = timestamp2 - timestamp1;

    如果把MemoryBlock c = std::move(a)换成MemoryBlock c = a;

    性能上大概也有30%的差距。

     

    这就是右值引用和移动构造语义带来的好处,我理解就是以前只能引用左值,而右值是不能引用的,新语法的加入实现了右值的引用,减少了零时对象的产生销毁,但是也带来了更多怪异的语法,明显增加了c++的学习成本,如果语法设计角度,像oc一样增加类似引用计数器来管理对象,会不会更加优雅一下,至少让上层的码农不会那么累,其实通智能指针也能达到同样的效果。

     

    这么多年了c++都在做加法,让学习,使用成本太高了,标准委员为的大爷些什么时候考虑一下做点减法呢,不要让c++那么学院派或者满地都是陷阱,也不要让实现一种技术有10种方法,但是有5种都是陷阱。靠!

  • 相关阅读:
    振动传感器
    水银开关式碰撞传感器
    倾斜传感器
    光敏传感器
    激光传感器的使用
    html字符串 转 json
    浏览器播放视频加快进功能
    处理箭头函数单个参数括号规则冲突
    VUE-directive指令之语法、引用、钩子函数、参数
    win10系统自动升级怎么还原到以前的系统
  • 原文地址:https://www.cnblogs.com/budaixi/p/3860457.html
Copyright © 2011-2022 走看看