假设我们有这种情况
std::string v_1()
{
return "name";
}
std::string test = v_1();RVO在这里申请吗?我认为答案是否定的,因为应用RVO的规则之一是:“如果函数按值返回类类型,而返回语句的表达式是具有自动存储持续时间的非易失性对象的名称(该对象不是函数参数,或者一个catch子句参数),而具有与函数的返回类型相同的类型(忽略顶级cv-资格),则省略复制/移动”,在这种情况下,返回的对象与函数的返回类型不同,但我不是100%认为RVO不适用于这里。
非常感谢。
PS。在这篇文章中,来自微软的https://www.youtube.com/watch?v=AKtHxKJRwp4 (分40分钟,第18分钟)谈到了一种无法应用RVO的情况,因为函数的返回类型与返回对象的类型不同(在他的示例中是元组对一对)。我认为同样的原则也适用于这里。
发布于 2016-12-03 19:02:10
我想你把NRVO和RVO搞混了。
NRVO -命名为返回值优化RVO -(未命名)返回值优化NRVO涉及一个命名变量,而RVO涉及在return语句中构造的未命名的临时变量。
视频上的示例是NRVO,当类型不同时,显然不能在调用方堆栈上构造命名对象,因为函数堆栈中必须存在一个类型的对象,而调用方堆栈上必须存在另一个类型的对象。
您的示例是RVO,其中没有使用预先构造的命名对象。在您的代码中,您正在构造一个临时对象作为返回值。因为这是暂时的,所以你引用的规则不适用。
根据C++11标准,我看不出为什么RVO不能发生:
12.8复制和移动类对象[ class.copy ] . 31 . --当没有绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-非限定类型的类对象时,可以通过将临时对象直接构造到省略副本/移动的目标中来省略复制/移动操作。
通过返回一个char array,将构造一个临时的std::string,这就是返回给调用者的内容。
发布于 2016-12-03 20:28:42
NRVO和RVO是不同的漏诊病例。
省略是将多个对象的生存期合并为一个对象的地方。
NRVO和RVO是编译器在标准允许时如何进行省略的名称。
在您的示例中,允许在return行上创建的临时变量、函数的返回值和存储返回值的命名变量之间进行省略。每个严肃的编译器都可以并且将这些值合并在一起,除非您明确地告诉它不要通过编译器标志。在C++17中,这些考虑将是强制性的。
https://stackoverflow.com/questions/40950427
复制相似问题