RVO是否适用于这种情况?
Is RVO applied on this situation?
假设我们有这种情况
std::string v_1()
{
return "name";
}
std::string test = v_1();
这里应用RVO了吗?我认为答案是否定的,因为应用 RVO 的规则之一是:“如果一个函数 return 是一个 class 类型的值,并且 return 语句的表达式是具有自动存储持续时间的非易失性对象的名称,它不是函数参数,也不是 catch 子句参数,并且 与return 类型的函数,则省略 copy/move"
在这种情况下,对象 returned 与函数的 return 类型不具有相同类型,但我不是 100% 认为 RVO 未在此处应用。
非常感谢。
PS。在本次演讲中 https://www.youtube.com/watch?v=AKtHxKJRwp4(第 40 分钟,第 18 秒)来自 Microsoft 的 Stephan 谈到了无法应用 RVO 的情况,因为函数的 return 类型与 returned 对象(在他的示例中是一个元组与一对)。我认为同样的原则也适用于此。
我认为您混淆了 NRVO
和 RVO
。
NRVO
- 命名 return 价值优化
RVO
- (未命名)return 价值优化
NRVO
涉及命名变量,而 RVO
涉及在 return
语句中构造的未命名临时变量。
视频中的示例是 NRVO
,其中 命名对象 显然不能在 调用程序堆栈 上构建当类型不同时,因为函数堆栈中必须存在一种类型的一个对象,而调用者堆栈中必须存在另一种类型的另一个对象。
您的示例是 RVO
,您没有使用预先构建的命名对象。在您的代码中,您正在 构造 一个 临时 对象作为 return 值。因为它是 临时 你引用的规则不适用。
根据 C++11
标准,我看不出 RVO
不能发生的原因:
12.8 Copying and moving class objects [ class.copy ]
...
31
...
-- when a temporary class object that has not been bound to a reference (12.2) would be copied/moved
to a class object with the same cv-unqualified type, the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted copy/move
通过 return 构建一个 char array
一个临时的 std::string
并且 就是 returned 到来电者。
NRVO 和 RVO 是省略的不同情况。
省略是将多个对象的生命周期合并到一个对象中。
名称 NRVO 和 RVO 是编译器在标准允许时如何进行省略的名称。
在您的示例中,在 return
行上创建的临时变量、函数的 return 值和存储 return 值的命名变量之间允许省略。每个严肃的编译器都可以并且将会一起删除这些值,除非您明确告诉它不要通过编译器标志。在 C++17 中,这些省略将是强制性的。
假设我们有这种情况
std::string v_1()
{
return "name";
}
std::string test = v_1();
这里应用RVO了吗?我认为答案是否定的,因为应用 RVO 的规则之一是:“如果一个函数 return 是一个 class 类型的值,并且 return 语句的表达式是具有自动存储持续时间的非易失性对象的名称,它不是函数参数,也不是 catch 子句参数,并且 与return 类型的函数,则省略 copy/move" 在这种情况下,对象 returned 与函数的 return 类型不具有相同类型,但我不是 100% 认为 RVO 未在此处应用。
非常感谢。
PS。在本次演讲中 https://www.youtube.com/watch?v=AKtHxKJRwp4(第 40 分钟,第 18 秒)来自 Microsoft 的 Stephan 谈到了无法应用 RVO 的情况,因为函数的 return 类型与 returned 对象(在他的示例中是一个元组与一对)。我认为同样的原则也适用于此。
我认为您混淆了 NRVO
和 RVO
。
NRVO
- 命名 return 价值优化RVO
- (未命名)return 价值优化
NRVO
涉及命名变量,而 RVO
涉及在 return
语句中构造的未命名临时变量。
视频中的示例是 NRVO
,其中 命名对象 显然不能在 调用程序堆栈 上构建当类型不同时,因为函数堆栈中必须存在一种类型的一个对象,而调用者堆栈中必须存在另一种类型的另一个对象。
您的示例是 RVO
,您没有使用预先构建的命名对象。在您的代码中,您正在 构造 一个 临时 对象作为 return 值。因为它是 临时 你引用的规则不适用。
根据 C++11
标准,我看不出 RVO
不能发生的原因:
12.8 Copying and moving class objects [ class.copy ] ... 31 ...
-- when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
通过 return 构建一个 char array
一个临时的 std::string
并且 就是 returned 到来电者。
NRVO 和 RVO 是省略的不同情况。
省略是将多个对象的生命周期合并到一个对象中。
名称 NRVO 和 RVO 是编译器在标准允许时如何进行省略的名称。
在您的示例中,在 return
行上创建的临时变量、函数的 return 值和存储 return 值的命名变量之间允许省略。每个严肃的编译器都可以并且将会一起删除这些值,除非您明确告诉它不要通过编译器标志。在 C++17 中,这些省略将是强制性的。