std::string 的对象真的可以移动吗?

Is a object of std::string really movable?

本文关键字:移动 真的 string 对象 std      更新时间:2023-10-16

正如我们所知,一个可移动对象是当它被分配给另一个相同类型的对象时不会被深度复制的对象。这样,我们可以节省大量时间。 但是今天,我发现了一个现象。请查看代码如下。

#include <string>
#include <iostream>
int main() {
std::string s1 = "s1";
std::string s2 = "s2";
std::cout << "  s1[" << ( void* ) &s1[0] << "]:" + s1
<< ", s2[" << ( void* ) &s2[0] << "]:" + s2
<< std::endl;
s1.swap( s2 );
std::cout << "  s1[" << ( void* ) &s1[0] << "]:" + s1
<< ", s2[" << ( void* ) &s2[0] << "]:" + s2
<< std::endl;
s2 = std::move(s1);
std::cout << "  s1[" << ( void* ) &s1[0] << "]:" + s1
<< ", s2[" << ( void* ) &s2[0] << "]:" + s2
<< std::endl;
return EXIT_SUCCESS; }

移动后,虽然字符串的内容发生了变化,但真正存储字符串数据的地址并没有改变。

如果内存添加不会更改,我们是否有理由确认实际上将执行深度复制,而不仅仅是指向目标成员的指针?

谢谢! 里昂

移动对象是分配时不会被深度复制的对象 到另一个相同类型

只有当它有意义时。 在以下代码片段中

int i0 = 11;
int i1 = std::move(i0);

不会仅仅因为没有什么可偷的而"偷窃"。 所以这个问题的前提是有缺陷的——如果有意义的话,移动操作会"窃取"移动的内容。

另请注意,在C++世界中,与 Java 和 C# 不同,对象是占用内存的所有内容 - 整数、指针、字符 - 所有这些都是对象。

std::string使用一种称为"短字符串优化"或 SSO 的优化技术。如果字符串足够短(并且定义了"足够短"的实现(,则不会动态分配缓冲区,因此不会"窃取"任何内容。当移动如此短的字符串时,字符串的内容非常短,只需复制到移入的字符串中,而不会弄乱动态分配的缓冲区。