You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17中移动省略(MOVE elision)有哪些变更?移动构造省略是否被保证?

C++17移动省略规则解答

核心规则调整

C++17引入的保证拷贝/移动省略不是可选的编译器优化,而是语言层面强制要求的规则:它重新定义了纯右值的语义,纯右值不再代表一个已经构造完成的临时对象,而是一个“待执行的对象初始化表达式”,只有在必须实体化出对象的时候才会触发构造。

这个规则不受-fno-elide-constructors编译选项影响,因为它不属于可选优化范畴,是语言强制要求的行为。

测试场景差异原因

你的测试代码中两种传参方式的行为差异可以直接用上述规则解释:

#include <iostream>

struct NonCopyable
{
  NonCopyable() = default;
  NonCopyable(const NonCopyable&) = delete;

  NonCopyable(NonCopyable&& other) noexcept
  {
    std::cout << "Move ctor\n";
  }
};

void func_by_value(NonCopyable cp)
{
  auto x = std::move(cp);
}

void func_by_rvalue_ref(NonCopyable&& cp)
{
  auto x = std::move(cp);
}

int main() 
{
  std::cout << "Pass by value:\n";
  func_by_value(NonCopyable());

  std::cout << "\nPass by rvalue_ref\n";
  func_by_rvalue_ref(NonCopyable());
}

按值传参场景 func_by_value(NonCopyable())

  • C++11/14规则:NonCopyable()先构造一个纯右值临时对象,再用这个临时对象移动构造函数的按值参数cp,触发第一次移动构造;函数内部auto x = std::move(cp)触发第二次移动构造,总共2次移动调用。
  • C++17规则:纯右值NonCopyable()直接在参数cp的内存地址上构造对象,不需要额外执行一次移动构造初始化参数,因此只剩下函数内部的1次移动构造调用。

右值引用传参场景 func_by_rvalue_ref(NonCopyable())

参数是右值引用,只需要绑定到临时对象不需要构造新的对象,所以C11和C17下行为一致,只有函数内部的1次移动构造调用。

补充注意点

保证省略仅适用于纯右值直接初始化同类型对象的场景,包括:

  • 函数按值返回纯右值
  • 用纯右值初始化按值传递的函数参数
  • 用纯右值直接构造同类型对象
    如果是将亡值(比如std::move返回的右值引用),则不适用保证省略规则,是否省略还是取决于编译器优化。

内容的提问来源于stack exchange,提问作者bielu000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 05:15:08