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; }
发现直接copy和move并没有什么区别。
实际上,move的最大用法应该是用于移动构造函数。
对于某些带了指针类型的类,在复制其对象时,一般要使用深拷贝,参考string。
string内置一个char *指针,当你拷贝了当前string对象时,你不应该只复制指针,而应该要新开一块内存,把原指针指向的内存复制过去。
但是有一种情况例外,如果我可以保证原对象不用了的话,那我就可以执行浅拷贝,直接把指针的值复制过去,这样可以省去复制指针指向内存的开销。
以string为例子,深拷贝是复制char *指向的内存,而浅拷贝直接复制指针。
move的作用只是把参数变成右值,然后触发移动构造函数,或者移动赋值函数,仅此而已。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~