c++ 右值以及move

之前对move一直存在误解,想得太万能了。

右值实际上就是临时内存,类似于(1+2),可以int &&number = 1+2; 

move的话是将参数变成自身类型的右值,然后赋值给其他变量。

我一开始以为move是交换两块内存的指针之类,复杂度是O(1)那种,后来测试了一下发现并不是这样。测试代码如下:

#include <iostream>
#include <string>
#include <utility>
#include <cstring>
#include <sys/time.h>
using namespace std;


uint64_t getCurrentTime()  
{  
   struct timeval tv;  
   gettimeofday(&tv,NULL);  
   return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}  


struct node {
    char str[20000000];
};

inline void testMove(node *node1, node *node2) {
    uint64_t startTime = getCurrentTime();
    (*node2) = move(*node1);
    uint64_t endTime = getCurrentTime();
    cout << "cost " << endTime - startTime << " us" << endl;

}

inline void testCopy(node *node1, node *node2) {
    uint64_t startTime = getCurrentTime();
    (*node2) = (*node1);
    uint64_t endTime = getCurrentTime(); 
    cout << "cost " << endTime - startTime << " us" << endl;
}


int main() {
    const uint32_t str1Len = 25000000, str2Len = 30000000;
    char *str1 = new char[str1Len], *str2 = new char[str2Len];
    memset(str1, 'a', str1Len);
    memset(str2, 'b', str2Len);
    node *node1 = (node *)str1;
    node *node2 = (node *)str2;
    testMove(node1, node2);
    testCopy(node1, node2);
#ifdef DEBUG_OUTPUT
    for (int i = 0; i < str1Len; i++) {
        cout << (char)str1[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < str2Len; i++) {
        cout << (char)str2[i] << " ";
    }
    cout << endl;
#endif
    return 0;
}
View Code

发现直接copy和move并没有什么区别。

实际上,move的最大用法应该是用于移动构造函数。

对于某些带了指针类型的类,在复制其对象时,一般要使用深拷贝,参考string。

string内置一个char *指针,当你拷贝了当前string对象时,你不应该只复制指针,而应该要新开一块内存,把原指针指向的内存复制过去。

但是有一种情况例外,如果我可以保证原对象不用了的话,那我就可以执行浅拷贝,直接把指针的值复制过去,这样可以省去复制指针指向内存的开销。

以string为例子,深拷贝是复制char *指向的内存,而浅拷贝直接复制指针。

move的作用只是把参数变成右值,然后触发移动构造函数,或者移动赋值函数,仅此而已。

 

posted @ 2019-07-17 10:50  酱油党gsh  阅读(282)  评论(0编辑  收藏  举报