C++ 字符串移动赋值交换值

C++ 字符串移动赋值交换值,c++,c++11,g++,C++,C++11,G++,我正在编写一些测试用例,发现了一个奇怪的行为 对字符串的移动指定不会删除第一个字符串的值,而是指定了目标字符串的值 示例代码: #include <utility> #include <string> #include <iostream> int main(void) { std::string a = "foo"; std::string b = "bar"; std::cout << a << std::endl;

我正在编写一些测试用例,发现了一个奇怪的行为

对字符串的移动指定不会删除第一个字符串的值,而是指定了目标字符串的值

示例代码:

#include <utility>
#include <string>
#include <iostream>

int main(void) {
  std::string a = "foo";
  std::string b = "bar";
  std::cout << a << std::endl;
  b = std::move(a);
  std::cout << a << std::endl;

  return 0;
}
预期结果:

$ ./string.exe
foo
因此,我的问题是:

  • 这是故意的吗
  • 是否只有字符串和/或STL对象才会发生这种情况
  • 自定义对象是否会发生这种情况(如用户定义的)
环境: Win10 64位 msys2 g++5.2

编辑

阅读可能重复的答案和@OMGtechy的答案后 我扩展了测试以检查小字符串优化

#include <utility>
#include <string>
#include <iostream>
#include <cinttypes>
#include <sstream>

int main(void) {
  std::ostringstream oss1;
  oss1 << "foo ";
  std::ostringstream oss2;
  oss2 << "bar ";
  for (std::uint64_t i(0);;++i) {
    oss1 << i % 10;
    oss2 << i % 10;
    std::string a = oss1.str();
    std::string b = oss2.str();
    b = std::move(a);
    if (a.size() < i) {
      std::cout << "move operation origin was cleared at: " << i << std::endl;
      break;
    }
    if (0 == i % 1000)
      std::cout << i << std::endl;
  }

  return 0;
}
#包括
#包括
#包括
#包括
#包括
内部主(空){
标准::ostringstream oss1;

oss1这可能是由于短字符串优化;也就是说,没有指向“移动”的内部指针,因此它最终就像一个副本一样工作

我建议您尝试使用大量字符的字符串;这应该足以绕过短字符串优化并展示您期望的行为


这是完全有效的,因为从对象移动的C++标准状态(有些例外,字符串不是C++ 11中的一个)应该处于有效但未指定的状态。< /P>您不正确地假设移动对象将处于“默认”状态。或者是空状态,从中移动的对象可以处于任何有效状态,在这种情况下,您的实现只是交换了值。但它没有复制:它似乎已经交换了字符串。这也是一种有效的移动方式,因为从中移动的对象的最终状态是未指定的;它只需要能够被销毁可能实现者发现交换这两个实例更容易,而不必在交换过程中清除源代码,如果有点意外,这也同样有效。

#include <utility>
#include <string>
#include <iostream>
#include <cinttypes>
#include <sstream>

int main(void) {
  std::ostringstream oss1;
  oss1 << "foo ";
  std::ostringstream oss2;
  oss2 << "bar ";
  for (std::uint64_t i(0);;++i) {
    oss1 << i % 10;
    oss2 << i % 10;
    std::string a = oss1.str();
    std::string b = oss2.str();
    b = std::move(a);
    if (a.size() < i) {
      std::cout << "move operation origin was cleared at: " << i << std::endl;
      break;
    }
    if (0 == i % 1000)
      std::cout << i << std::endl;
  }

  return 0;
}