先看代码
#include <iostream>
#define PRINT_STRING(x) \
std::cout << #x << " = "; \
x.Print(); \
std::cout << std::endl;
class String
{
public:
String() = default;
String(const char *string)
{
std::cout << "Constructor" << std::endl;
m_Size = strlen(string);
m_Data = new char[m_Size];
memcpy(m_Data, string, m_Size);
}
String(const String &other)
{
std::cout << "Copy Constructor" << std::endl;
m_Size = other.m_Size;
m_Data = new char[m_Size];
memcpy(m_Data, other.m_Data, m_Size);
}
String(String &&other) noexcept
{
std::cout << "Move Constructor" << std::endl;
m_Size = other.m_Size;
m_Data = other.m_Data;
other.m_Size = 0;
other.m_Data = nullptr;
}
String &operator=(const String &other)
{
std::cout << "Copy Assignment" << std::endl;
if (this != &other)
{
delete[] m_Data;
m_Size = other.m_Size;
m_Data = new char[m_Size];
memcpy(m_Data, other.m_Data, m_Size);
}
return *this;
}
String &operator=(String &&other) noexcept
{
std::cout << "Move Assignment" << std::endl;
if (this != &other)
{
delete[] m_Data;
m_Size = other.m_Size;
m_Data = other.m_Data;
other.m_Size = 0;
other.m_Data = nullptr;
}
return *this;
}
~String()
{
std::cout << "Destructor" << std::endl;
delete[] m_Data;
}
void Print()
{
for (uint32_t i = 0; i < m_Size; ++i)
{
printf("%c", m_Data[i]);
}
printf("\n");
}
private:
uint32_t m_Size;
char *m_Data;
};
int main()
{
String string = "Hello";
String dest = std::move(string); // operator= means Move Constructor here
std::cout << "Before assignment-----------" << std::endl;
PRINT_STRING(string);
PRINT_STRING(dest);
string = std::move(dest); // operator= means Move Assignment here,
// which means the discrepancy between the two methods is
// whether the object that calls the function (operator=) is existing or not.
std::cout << "After reassignment-----------" << std::endl;
PRINT_STRING(string);
PRINT_STRING(dest);
}
把这段代码粘贴到自己的编译器中, 开启单步调试, 重点关注string和dest这两个对象下面的m_Data内存地址的变化
你就能了解到,为什么这么多人说,移动语义本质上就是"偷"了.