根据具体实现,std::move 可以是内部内存地址的简单交换。
如果你在http://cpp.sh/9f6ru上运行以下代码
#include <iostream>
#include <string>
int main()
{
std::string str1 = "test";
std::string str2 = "test2";
std::cout << "str1.data() before move: "<< static_cast<const void*>(str1.data()) << std::endl;
std::cout << "str2.data() before move: "<< static_cast<const void*>(str2.data()) << std::endl;
str2 = std::move(str1);
std::cout << "=================================" << std::endl;
std::cout << "str1.data() after move: " << static_cast<const void*>(str1.data()) << std::endl;
std::cout << "str2.data() after move: " << static_cast<const void*>(str2.data()) << std::endl;
}
你会得到以下输出:
str1.data() before move: 0x363d0d8
str2.data() before move: 0x363d108
=================================
str1.data() after move: 0x363d108
str2.data() after move: 0x363d0d8
但结果可能会因编译器和标准库的实现而异。
但实现细节可能更复杂http://cpp.sh/6dx7j。如果您查看您的示例,那么您将看到为字符串创建副本并不一定需要为其内容分配新内存。这是因为std::string 上的几乎所有操作都是只读的或需要分配内存。所以实现可以决定只做浅拷贝:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
std::cout << "str.data() before move: "<< static_cast<const void*>(str.data()) << std::endl;
v.push_back(str);
std::cout << "============================" << std::endl;
std::cout << "str.data() after push_back: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after push_back: "<< static_cast<const void*>(v[0].data()) << std::endl;
v.push_back(std::move(str));
std::cout << "============================" << std::endl;
std::cout << "str.data() after move: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after move: "<< static_cast<const void*>(v[0].data()) << std::endl;
std::cout << "v[1].data() after move: "<< static_cast<const void*>(v[1].data()) << std::endl;
std::cout << "After move, str is \"" << str << "\"\n";
str = std::move(v[1]);
std::cout << "============================" << std::endl;
std::cout << "str.data() after move: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after move: "<< static_cast<const void*>(v[0].data()) << std::endl;
std::cout << "v[1].data() after move: "<< static_cast<const void*>(v[1].data()) << std::endl;
std::cout << "After move, str is \"" << str << "\"\n";
}
输出是
str.data() before move: 0x3ec3048
============================
str.data() after push_back: 0x3ec3048
v[0].data() after push_back: 0x3ec3048
============================
str.data() after move: 0x601df8
v[0].data() after move: 0x3ec3048
v[1].data() after move: 0x3ec3048
After move, str is ""
============================
str.data() after move: 0x3ec3048
v[0].data() after move: 0x3ec3048
v[1].data() after move: 0x601df8
After move, str is "Hello"
如果你看一下:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
std::cout << "str.data() before move: "<< static_cast<const void*>(str.data()) << std::endl;
v.push_back(str);
std::cout << "============================" << std::endl;
str[0] = 't';
std::cout << "str.data() after push_back: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after push_back: "<< static_cast<const void*>(v[0].data()) << std::endl;
}
然后你会假设str[0] = 't' 会替换原地的数据。但这不一定是http://cpp.sh/47nsy。
str.data() before move: 0x40b8258
============================
str.data() after push_back: 0x40b82a8
v[0].data() after push_back: 0x40b8258
以及移动原语,例如:
void test(int i) {
int x=i;
int y=std::move(x);
std::cout<<x;
std::cout<<y;
}
大部分会被编译器完全优化:
mov ebx, edi
mov edi, offset std::cout
mov esi, ebx
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, offset std::cout
mov esi, ebx
pop rbx
jmp std::basic_ostream<char, std::char_traits<char> >::operator<<(int) # TAILCALL
std::cout 使用相同的寄存器,x 和 y 被完全优化掉。