/Zc:nrvo
(控制可选 NRVO)
/Zc:nrvo
编译器选项控制标准 C++ 可选命名返回值优化 (NRVO) 复制或移动省略行为。
语法
]$
备注
在 Visual Studio 2022 版本 17.4 及更高版本中,可以使用/Zc:nrvo
编译器选项显式启用可选复制或移动省略行为。 此选项默认关闭,但在使用/O2
选项、/permissive-
选项或/std:c++20
或更高版本进行编译时,会自动设置此选项。 在/Zc:nrvo
下,尽可能地执行复制和移动省略。 也可以使用/Zc:nrvo-
选项显式禁用可选复制或移动省略。 这些编译器选项仅控制可选复制或移动省略。 不能禁用强制复制或移动省略(由 C++ 标准版指定)。
强制复制和移动省略
当返回值初始化为 return 语句的一部分时,C++ 标准需要复制或移动省略。 例如,当函数返回使用return ExampleType();
返回的ExampleType
时,它是必需项。 MSVC 编译器在需要时始终对return
语句执行复制和移动省略,即使在/Zc:nrvo-
下也是如此。
可选复制并移动省略
当return
语句包含非基元类型的表达式时,其执行会将表达式结果复制到调用函数的返回槽。 编译器调用返回类型的复制或移动构造函数。 然后,当函数退出时,会调用函数局部变量的析构函数,其中包括表达式中命名的任何变量。
C++ 标准允许(但不要求)编译器直接在调用函数的返回槽中构造返回的对象。 此构造跳过(或略过)作为return
语句的一部分执行的复制或移动构造函数。 与其他大多数优化不同,允许此转换对程序的输出产生可观测的影响。 也就是说,会减少调用复制或移动构造函数和相关析构函数一次。 该标准仍要求命名的返回变量具有定义的复制或移动构造函数,即使编译器在所有情况下都会略过构造函数。
在 Visual Studio 2022 版本 17.4 之前的版本中,当优化被禁用(例如,在/Od
下或标记为#pragma optimize("", off)
的函数中)时,编译器仅执行强制复制和移动省略。 在/O2
下,当满足所有这些条件时,较旧的编译器对在优化函数中返回命名变量执行可选复制或移动省略:它没有循环或异常处理,它不返回具有重叠生存期的多个符号,类型的副本或移动构造函数没有默认参数。
Visual Studio 2022 版本 17.4 增加了编译器在/Zc:nrvo
下执行可选复制或移动省略的位置数,无论是显式启用还是通过使用/O2
、/permissive-
或/std:c++20
或更高版本选项自动启用。 在/Zc:nrvo
下,编译器在以下情况下对返回任何函数的命名变量执行可选复制或移动省略:它没有循环或异常处理(如前所述):它从循环返回变量;它具有异常处理;返回类型的复制或移动构造函数具有默认参数。 应用/Zc:nrvo-
或函数返回具有重叠生存期的多个符号或引发命名变量时,永远不会执行可选复制或移动省略。
有关/Zc:nrvo
下强制和可选复制省略的详细信息和示例,请参阅 C++ 团队博客中的改进复制和移动省略。
在 Visual Studio 中设置此编译器选项
打开项目的“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
选择“配置属性”>“C/C++”>“命令行”属性页。
在其他选项中添加
/Zc:nrvo
或/Zc:nrvo-
。 选择“确定”或“应用”以保存更改。