C++ 中 move 语义的理解

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 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 语义的理解)