Defensive Copies in Modern C++

现代 C++ 以不同的方式解决此问题:

std::string s1 = "Cpp";
std::string s2 = s1;  // 复制 s1 中的数据。
  • s1 中的堆数据被复制,s2 获得自己的独立副本。
  • s1s2 离开作用域时,它们会各自释放自己的内存。

复制-赋值之前:

StackHeaps1ptrCpplen3capacity3

复制-赋值之后:

StackHeaps1ptrCpplen3capacity3s2ptrCpplen3capacity3

关键点:

  • C++ 做出了与 Rust 略有不同的选择。由于“=”会复制数据,因此必须克隆字符串数据。否则,当任一字符串超出范围时,便会出现二次释放。

  • C++ 还包含“std::move”,它用于指示何时可以移动某个值。如果示例为“s2 = std::move(s1)”,则不会发生堆分配。移动后,“s1”将处于有效但未指定的状态。与 Rust 不同,程序员可以继续使用“s1”。

  • 与 Rust 不同,使用 C++ 时,“=”可以运行任意代码,具体取决于要复制或移动的类型。