【问题标题】:Xcode - shallow copy in STL string assignmentXcode - STL 字符串赋值中的浅拷贝
【发布时间】:2015-08-01 08:40:10
【问题描述】:

在 Xcode 中运行以下 C++ 代码时:

std::wstring str1 = L"1111";
std::wstring str2 = str1;

void* ptr1 = (void*)str1.c_str();
void* ptr2 = (void*)str2.c_str();

结果是两个指针相等。这是按标准吗? 在 Visual Studio 中并非如此。

【问题讨论】:

  • 您使用的是什么版本的 Xcode?我在 mac 上使用 Xcode/clang 没有得到这个结果。
  • Xcode 6.3.1 和 C++ 方言 gnu++11(编译器选项:-std=gnu++11)
  • 建议您使用 -stdlib=libc++ 选项。这是一个更符合标准的实现,是新项目的默认设置。

标签: c++ xcode string c++11 stl


【解决方案1】:

看起来该实现正在使用 copy-on-write (COW) 优化,其中字符串内部状态仅在执行写入操作时才真正设置*支持>。这在 C++11 之前的实现中是允许的,但我不认为这是自 C++11 以来的标准。

请注意,当您以非常量方式访问字符串时,您可以检查底层指针的地址是否发生变化,即使没有写入它:

str2[0];

对这个表达式的求值应该触发一个写操作,这会改变指针的地址。这是一个工作示例:

#include <string>
#include <iostream>

int main() 
{
  std::wstring str1 = L"1111";
  std::wstring str2 = str1;

  std::cout << (void*)str1.c_str() << " " << (void*)str2.c_str() << std::endl;

  str2[0]; // forces a write operation. c_str() changes.

  std::cout << (void*)str1.c_str() << " " << (void*)str2.c_str() << std::endl;
}

在最近的 gcc 上,这会产生

0x8a8e014 0x8a8e014
0x8a8e014 0x8a8e03c

* 一些非常量访问可以触发写入,即使它们没有在语义上改变字符串,如上例所示。

【讨论】:

  • 我们使用的是 gnu++11 方言,它与 C++11 不完全兼容,所以可能是这种情况。谢谢!
  • @OferB 我认为 gcc 4 系列不符合 w.r.t 标准。 COW,即使在 C++11 或 C++14 模式下。至少这不是我几个月前检查的最后一次。
猜你喜欢
  • 2012-02-28
  • 2012-11-19
  • 2011-08-29
  • 2013-06-19
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
相关资源
最近更新 更多