函数形参类型与返回值类型
参考:
- https://www.zhihu.com/question/22941176
- https://www.zhihu.com/question/534389744
注意,不探讨 const
1. 函数形参
1.1 实参、形参组合
我们知道 c++ 中函数形参可以有如下几种:
- 左值
- 左值引用
- 右值引用
而实参也可以有如下几种:
- 左值/左值引用
- 右值
将他们组合起来,形参有如下情况:
- 形参为左值:
- 实参为左值/左值引用,那么会发生拷贝构造行为,语义上可以看作资源被复制了一份
- 实参为右值,那么会发生移动构造行为,语义上可以看作资源发生了转移,caller 不再拥有实参的资源所有权
- 形参为左值引用:
- 实参为左值/左值引用,不会发生任何构造行为,语义上可以看作资源被共享了一份
- 实参为右值,语法错误
- 形参为右值引用:
- 实参为左值/左值引用,语法错误
- 实参为右值,也不会发生任何构造行为,语义上可以看作临时资源被共享了一份。但是实际上,一般右值引用作为形参的函数都是 callee 在函数内部进行移动构造,以转移资源所有权
1.2 智能指针作为形参
智能指针作为形参时,形参类型为左值、右值引用、左值引用都可以。
但是考虑到智能指针是带有引用计数功能的类,从智能指针的设计语义出发,形参为左值引用应该被排除。形参为右值引用意味着 caller 要转移对象资源,由于智能指针类都设计有移动构造(unique_ptr、shared_ptr),所以直接用左值接受即可。
2. 函数返回值
我们知道 c++ 中函数返回值可以有如下几种:
- 左值(如果没有开启返回值优化特性,实际上对 caller 来说返回的是一个右值,关于返回值优化,参看 )
- 左值引用
- 右值引用
函数返回的值本身,有如下属性:
- 非临时对象
- 临时对象
2.1 返回非临时对象
2.1.1 不转移对象所有权(返回左值或左值引用)
如果返回:
- 左值,caller 不能采用左值引用进行接收(对于 caller 来说,返回的左值实际上语法上是个临时对象,是个右值)。且会触发返回值优化特性
- 左值引用,caller 可以采用左值引用进行接收。也可以采用左值进行接收,触发拷贝构造/赋值构造
2.1.2 转移对象所有权(返回左值或右值引用)
如果返回:
- 左值,会触发返回值优化特性
- 右值引用,也会触发返回值优化特性
2.2 返回临时对象
临时对象返回左值即可,使用左值接收,以触发返回值优化。如果返回引用,无论左值引用还是右值引用,caller 接收对象都是未定义行为