美文网首页CPP
C++ 中 move 语义的理解

C++ 中 move 语义的理解

作者: 顽强的猫尾草 | 来源:发表于2018-08-21 15:45 被阅读79次

    std::move 是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。

    string 类在赋值或者拷贝构造函数中会声明 char* 数组来存放数据,然后原 string 中的 char* 数组被析构函数释放,如果 s 是一个临时变量,则上面的拷贝和析构就是多余的,完全可以把临时变量 s 中的数据直接 “转移” 到新的变量下面。

    move 语义的场景中,往往都是一个临时对象传给了一个函数,C++11 语法规定:将一个右值(比如一个临时对象表达式)传给一个函数的时候,是优先绑定到参数形式是右值引用的函数上的。

    【示例 1】s0 + " world." 这个表达式是个右值,因为它的结果是个临时对象,str 对象的构造函数在 C++11 之前调用的是传统的 Copy Ctor,而在 C++11 中会优先调用 Move Ctor。

    std::string s0 = "hello";
    std::string str = s0 + " world.";
    

    看起来 move 和浅拷贝没有什么区别?但其实它还把源对象清空了。根据对象类别不同清空操作也不同,如果是指针就是置 nullptr,如果是容器类就 clear 所有元素。所以如果原先的对象还想使用一定要注意需不需要重新初始化。

    【示例 2】在将集合类型 newList 通过 move 语义传给 tmpList 后,newList 变为空集合,仍然可以使用:

    std::set<string> newList;
    // add IPs to newList
    ...
    
    auto portStr = "9000";
    auto tempList = std::move(newList);
    for (auto & ipPort : tempList) {
        auto index = ipPort.find(':');
        if (std::string::npos == index) {
            continue;
        }
        auto ip = ipPort.substr(0, index);
        auto newIpPort = ip + ":" + portStr;
        newList.insert(newIpPort);
    }
    

    其中,npos 是一个常数,表示 size_t 的最大值。许多容器都提供这个常数,用来表示不存在的位置。在 string 类中,find() 方法在找不到指定值的情况下会返回 string::npos

    move 是和 copy 相对的:

    • copy 就是照着别人的东西复制一份,所需的工作量随拷贝对象的不同而不同,比如拷贝一个字很快,拷贝一本书很慢。
    • move 就是把别人书上的名字擦掉,写上自己的。因为 move 不需要复制,所以很快。其实就是把自己的指针指过去,把原属主的指针指向别处。

    相关文章

      网友评论

        本文标题:C++ 中 move 语义的理解

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