从函数返回 const 对象是否会阻止从外部移动构造

Will returning a const object from a function prevent move construction from outside?

本文关键字:从外部 移动 返回 函数 const 对象 是否      更新时间:2023-10-16

给定此函数和函数调用:

std::string GetString() {
  std::stringstream sstr;
  const auto str = sstr.str();
  return str;
}
const auto returnedStr = GetString();

当我宣布str为常量时,移动结构会被省略吗?

在您的情况下,returnedStr将从 GetString() 的返回值移动构造,但该返回值将从str (1( 复制构造。如果str没有const,则返回值将从中移动构造。

请注意,在这两种情况下,返回值优化仍然适用,因此编译器仍然可以直接在returnedStr空间中构造返回值(甚至str本身(,跳过一个或两个复制/移动构造。这是由 C++11 12.8/31 授予的:

当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使对象的复制/移动构造函数和/或析构函数具有副作用。在这种情况下, 该实现将省略的复制/移动操作的源和目标视为两个不同的 指代同一对象的方式,以及该对象的破坏发生在较晚的时间 当两个对象在没有优化的情况下被销毁时。复制/移动的省略 在以下情况下允许操作,称为复制省略(可以合并到 消除多个副本(:

  • 在具有类返回类型的函数的 return 语句中,当表达式是 具有相同 CV 不合格的非易失性自动对象(函数或 catch 子句参数除外( 类型作为函数返回类型,可以通过构造来省略复制/移动操作 自动对象直接进入函数的返回值

  • 当尚未绑定到引用 (12.2( 的临时类对象将被复制/移动时 对于具有相同 CV 非限定类型的类对象,可以省略复制/移动操作 将临时对象直接构造到省略的副本/移动的目标中

第一个要点涵盖了返回值构造的省略,另一个项目符号涵盖了将返回值移动到returnedStr。请注意对"相同的 cv 不合格"类型的要求,这意味着无论 cv 限定符如何,这都有效。


(1(请注意,如果我们谈论的是除std::string以外的类X,它提供了一个采用const X&&的移动构造函数,那么返回值确实是使用该构造函数(无论它可能具有什么语义(构造的移动。

Angew的回答是对的,但谁能记住所有的语言律师规则?

为了帮助我更容易记住它,我写了以下规则,这些规则来自STL自己的嘴。

  1. 不要将当地人返回为常量 [16]

$ 抑制移动语义

  1. 按值返回本地时不使用 move完全相同的类型 [16]

如果这样做,将不会使用 NREVO 。

  1. 不要通过右值引用 (&&( 返回 [16]

$ 除非你真的知道你在做什么。

笔记:

[16] 不要帮助编译器,走向原生 2013,http://www.youtube.com/watch?v=AKtHxKJRwp4