复制和修改时出现无法解释的差异std::strings

Unexplained discrepancies when copying and modifying std::strings

在下面的代码中,"situation 1" 在所有 编译器经过测试,但是 "situation 2" 它似乎表现不同 基于所使用的编译器。

举个例子,MSVC 让 sit1 和 sit2 产生相同的结果,但是 使用 gcc/clang 和 libstdc++ 时,修改发生在 原始字符串及其副本 (有点像 COW 字符串) 即使 我正在使用 C++11 开关进行构建。

#include <iostream>
#include <string>

int main() {

   // situation 1
   {
      std::string x0 = "12345678";
      std::string x1 = x0;

      char* ptr = &x0[0] + 3;

      (*ptr) = ' ';

      std::cout << "1. x0: " << x0 << "\n";
      std::cout << "1. x1: " << x1 << "\n";

      if ((&x0[0]) == x0.data()) std::cout << "1. ptrs are equal\n";

   }

   // situation 2
   {
      std::string x0 = "12345678";
      std::string x1 = x0;

      char* ptr = const_cast<char*>(x0.data() + 3);

      (*ptr) = ' ';

      std::cout << "2. x0: " << x0 << "\n";
      std::cout << "2. x1: " << x1 << "\n";

      if ((&x0[0]) == x0.data()) std::cout << "2. ptrs are equal\n";
   }

   return 0;
}

海湾合作委员会 (6.1)

1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 123 5678
2. ptrs are equal

MSVC (2015)

1. x0: 123 5678
1. x1: 12345678
1. ptrs are equal
2. x0: 123 5678
2. x1: 12345678
2. ptrs are equal

考虑到 &x0[0] 和 .data() return 相同的地址,各种编译器之间的行为差​​异是否有任何原因?

情况 2 导致未定义的行为:

char* ptr = const_cast<char*>(x0.data() + 3);

(*ptr) = 'Z';

根据std::basic_string::data (C++14 [string.accessors]/3)的规范:

Requires: The program shall not alter any of the values stored in the character array.

换句话说,您不能丢弃 const 并通过 data()c_str() 返回的指针修改字符串。