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

时间:2018-10-20 09:21:08

标签: c++ string pointers move-semantics

我们知道,将一个可移动对象分配给相同类型的另一个对象时,不会深深地复制它。这样,我们可以节省很多时间。 但是今天,我发现一种现象在我眼前。请查看以下代码。

#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; }

移动后,虽然字符串的内容已更改,但实际存储字符串数据的地址未更改。

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

谢谢! 莱昂

1 个答案:

答案 0 :(得分:5)

  

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

仅在有意义的情况下。在以下代码段中

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

不会因为没有什么可窃取而进行“窃取”。因此问题的前提是有缺陷的-移动操作会在合理的情况下“窃取”移动内容。

还要注意,在C ++世界中,与Java和C#不同,对象是所有占用内存的东西-整数,指针,字符-它们都是对象。

std::string使用称为“短字符串优化”或SSO的优化技术。如果该字符串足够短(并且定义了“足够短”的实现),则不会动态分配缓冲区,因此没有任何内容可以“窃取”。当移动这样的短字符串时,字符串的内容是如此之短,以至于它被复制到移入的字符串中,而不会弄乱动态分配的缓冲区。