【问题标题】:Is a object of std::string really movable?std::string 的对象真的可以移动吗?
【发布时间】:2018-10-20 09:21:08
【问题描述】:

正如我们所知,一个可移动的对象在分配给另一个相同类型的对象时不会被深度复制。通过这种方式,我们可以节省很多时间。 但是今天,我发现了一个对我来说很奇怪的现象。请查看以下代码。

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

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

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

谢谢! 里昂

【问题讨论】:

  • 你得到的输出是什么?预期的输出是什么?
  • 是的,std::string(C++11 起)可以移动,即它支持移动语义。

标签: c++ string pointers move-semantics


【解决方案1】:

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

只有在有意义的情况下。在下面的sn-p

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

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

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

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

【讨论】:

  • 我尝试了几次不同数量的字符。正如你所说,当要移动的字符数等于/大于 16 时,两者的地址都会改变。如果两个数字都小于 16,它只是简单地复制缓冲区。再次感谢你!莱昂
猜你喜欢
  • 2015-02-07
  • 2018-03-22
  • 2020-07-30
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多