复制elision、std::move和链式函数调用
Copy elision, std::move, and chained function calls
我一直在研究复制省略在没有直接分配给左值并且可能被链接或在以后使用时的行为,但没有找到任何具体的答案。
首先,我理解NRVO出现在以下示例中,返回值直接构建在目标变量中:
Type MakeType() {
Type type;
// ...
return type;
}
Type a = MakeType();
然而,假设我们有另一个函数,它将类型作为参数:
Type MakeComplexType(/*some signature*/ param_type) {
Type complex_type = param_type
// ...
return complex_type;
}
我们称之为:
Type t = MakeComplexType(MakeType());
- 是否可以将省略复制一直链到
t
- 如果没有,我们是否可以战略性地使用
std::move
,也许是在像std::move(MakeType())
这样的函数调用本身上,以避免不必要的复制 param_type
的签名应该是什么,使得上面对t
的分配是最有效的
拷贝省略是编译器用来防止不需要的拷贝的技术。基本上,它在函数之外预先分配内存,并将其传入以供使用。如果是临时的,它将在堆栈上。
将std::move添加到返回类型没有帮助。您已经按值返回了,所以您已经有了一个右值。用std:"移动应该是一个no-op吗?"。然而,我不知道细节,在某些情况下,添加它可能会影响性能。
重点关注2:在函数调用中添加std::move只会在非常量引用返回时产生副作用。在这些情况下,您很可能编写了一个bug,因为原来的bug将被移走。
对于编号3:我最喜欢使用f(Arg &&a)
,因为这需要所有调用方传递右值。如果性能不那么重要,例如:您在评测中没有发现它。值参数(某些调用方可以复制(甚至常量引用都可以(函数不能接触参数,所以应该复制(。
如注释所示,函数的实现也应该编写auto result = std::move(a)
,因为您的参数没有从NRVO中受益。
Clang的最新版本对什么时候应该使用std::move以及什么时候删除它有很好的警告。我建议启用它们。GCC可能会有一些类似的警告,但我还没有跟上
简而言之:您的原始代码是最好的版本,如果编译器对此有警告,请相信它。
相关文章:
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 复制elision、std::move和链式函数调用
- 为什么我的代码中没有调用move构造函数
- 如何调用move构造函数
- 复制初始化:为什么即使关闭了复制省略,也没有调用move或copy构造函数
- 如何在基类中调用 "move" '&&' 构造函数?在C++
- 与move构造函数配对时,会发生意外的析构函数调用
- 为什么这个函数不调用move构造函数
- 为什么std::move之后的析构函数调用是必要的
- 我是否应该对非引用构造函数参数手动调用move
- 确保调用move构造函数
- 为什么在没有std::move的情况下不调用move构造函数
- 如何调用move构造函数
- 当调用move构造函数时感到困惑
- 使用隐式可转换对象调用move重载函数时的编译错误
- 通过调用Move赋值操作符实现Move构造函数
- 为什么throw局部变量调用move构造函数
- 为什么没有调用move构造函数
- 为什么这里调用move构造函数
- 为什么在返回临时对象之前调用move构造函数?