函数形参类型与返回值类型


参考:

  • 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 接收对象都是未定义行为

C++