std::move实操

本文详细介绍了C++中的std::move用法,通过官方及自定义例子展示了如何将左值转换为右值引用,以及在容器如vector中的应用。在std::move作用下,对象可以高效地转移所有权,但需要注意在特定情况下可能影响原对象状态。同时提供了深入学习左值与右值、constexpr等相关概念的参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.用法

std::move用来指示对象t可以“被移动”, 即允许从t到另一种对象的高效率的转换
效果就是static_cast强转的作用。通过把左值的数据转换成右值,如果push_back,之后就可以直接传递指针。

2.官方例子

#include <iostream>
#include <utility>
#include <vector>
#include <string>
 
int main()
{
    std::string str = "Hello";
    std::vector<std::string> v;
 
    // 使用 push_back(const T&) 重载,
    // 表示我们将带来复制 str 的成本
    v.push_back(str);
    std::cout << "After copy, str is \"" << str << "\"\n";
 
    // 使用右值引用 push_back(T&&) 重载,
    // 表示不复制字符串;而是
    // str 的内容被移动进 vector
    // 这个开销比较低,但也意味着 str 现在可能为空。
    v.push_back(std::move(str));
    std::cout << "After move, str is \"" << str << "\"\n";
 
    std::cout << "The contents of the vector are \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";
}

3. 我的例子

#include<iostream>
#include<string>
#include<vector>
#include<utility>

//定义自己的move
namespace csstd{
    /*define remove_reference overload*/
    template<typename _Tp> 
    struct remove_reference
    {typedef _Tp type;};

    template<typename _Tp> 
    struct remove_reference<_Tp&>
    {typedef _Tp type;};

    template<typename _Tp> 
    struct remove_reference<_Tp&&>
    {typedef _Tp type;};
    
    template<typename _Tp>
        constexpr typename csstd::remove_reference<_Tp>::type&&
        move(_Tp&& __t) noexcept
        { return static_cast<typename csstd::remove_reference<_Tp>::type&&>(__t);}
}

void TESTSTLMOVE() {
    std::string str = "hello";
    std::vector<std::string> vec;
    
    //push the value into the vector arrary;
    vec.push_back(str);
    std::cout << "After copy the value is " << str << std::endl;

    //After using the move function to push back the str value;
    vec.push_back(std::move(str));
    std::cout << "After using move function, copy the value is \"" << str << "\"\n";
    std::cout << "the first value of vector is " << vec[0] << "the second value is " <<
                vec[1] << std::endl;
}

class MemoryBlock {
public:
    //default constructor
    MemoryBlock(size_t size)
        : _size(size)
        , _data(new int[size])
        {
            std::cout << "default constructor size is " << _size
                    << std::endl;
        }
    //destructor
    ~MemoryBlock(){
        std::cout << "In memory destrcutor, length is " << _size << std::endl;
        if (_data != nullptr) {
            std::cout << "delete the _data" <<std::endl;
            delete [] _data;
        }
    }
    //copy construct
    MemoryBlock(const MemoryBlock& block)
        : _size(block._size)
        , _data(new int[_size])
    {
        std::cout << "In copy construct, length is " << _size << std::endl;
        std::copy(block._data, block._data + _size, _data);
    }
    //operator overload
    MemoryBlock& operator=(const MemoryBlock& other) 
    {
        if (this != &other) {
            delete[] _data;
            _size = other.getSize();
            _data = new int[_size];
            std::copy(other._data, other._data + _size, _data);
        }
        return *this;
    }
    size_t getSize() const{
        return _size;
    }
    //move construct
    MemoryBlock(MemoryBlock&& block)
        : _data(block._data)
        , _size(block._size)
    {
        std::cout << "In move construct, length is " << _size << std::endl;
        block._size = 0;
        block._data = nullptr;
    }

    MemoryBlock& operator=(MemoryBlock&& block)
    {
        std::cout << "In move copy construct, length is " << block._size << std::endl;
        if (&block != this) {
            delete[] _data;

            _data = block._data;
            _size = block._size;

            block._data = nullptr;
            block._size = 0;
        }
        return *this;
    }
        
    //move assignment operator
private:
    size_t _size;
    int* _data;
};

void TESTObjwithoutMOVE() {
    std::vector<MemoryBlock> v;
    MemoryBlock m1(25);
    MemoryBlock m2(24);
    MemoryBlock m3(24);
    v.push_back(m1);
    v.push_back(m2);
    v.push_back(m3);
    v.push_back(m3);
    //v.push_back(mm);
    //v.push_back(csstd::move(mm));
    //v.push_back(mm);
   // std::cout << "the mm is " << mm.getSize() << std::endl;
    std::cout << v.size() << std::endl;
}
void TESTObjwithMove()
{
    std::vector<MemoryBlock> v;
    MemoryBlock m1(25);
    MemoryBlock m2(24);
    MemoryBlock m3(24);
    v.push_back(csstd::move(m1));
    v.push_back(m2);
    v.push_back(m3);
    v.push_back(csstd::move(m2));
    //v.push_back(mm);
    //v.push_back(csstd::move(mm));
}

int main() {
    //TESTSTLMOVE();
    TESTObjwithoutMOVE();
    std::cout << "-----------------------" << std::endl;
    TESTObjwithMove();
    return 0;
}

通过例子可以看到在std::move传入值时,只是传入指针的值,并没有做拷贝构造函数,但是当vector超过capacity的时候,进行再次的copy构造函数时,会对原有的值有影响。例子中我们模拟了std::move的执行

 

4.参考


&&参数:https://docs.microsoft.com/en-us/cpp/cpp/rvalue-reference-declarator-amp-amp?view=vs-2019
左值与右值:https://docs.microsoft.com/en-us/cpp/cpp/lvalues-and-rvalues-visual-cpp?view=vs-2019

constexpr:https://en.cppreference.com/w/cpp/language/constexpr

左值右值:https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/index.html

https://docs.microsoft.com/en-us/cpp/cpp/lvalues-and-rvalues-visual-cpp?view=vs-2019

move相关文献:https://docs.microsoft.com/en-us/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=vs-2019

https://blog.youkuaiyun.com/swartz_lubel/article/details/59620868

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值