函数传参、模板传参、右值引用

函数传参

普通函数

非常量引用

在普通函数中,当形参是一个类型的引用时:

void f1(int&);

那么,函数f1可以接受下列形式的实参:

  • 一个变量,非const
    有名字的变量。
  • 返回int &类型的表达式或者是函数。
    不能是int

不接受常量,或者是匿名变量,比如我们直接传一个1,不能接受const int类型的实参。

常量引用

当函数的形参是一个常量引用时:

void f2(const int &);

那么函数f2可以接受下列形式的实参:

  • 一个变量
    可以使const,也可是不是
  • 常量类型的int
  • 匿名变量
    直接是数值
  • 一个返回int类型的表达式或函数
    或是const都行。

可见,常量的形参限制小,但是因为不能改变传入参数的值。

模板函数

值类型

当函数是一个模板的时候:

template <typename T>
void f3(T t);

那么,函数f3可以接受上面两种普通函数的形式。
因为T可以被推断为const int,和int
只是值类型的

引用类型

因此如果,想要声明为引用需要:

template <typename T>
void f4(T&);

这样就和普通函数的第一种形式相同 了。
同时参数也可以是const T&

右值引用

上面普通函数的都是左值类型的参数
下面是右值引用

void f(string &&);

普通函数的右值引用可以接受下列形式的实参:

  • 常量表达式
    一个数字,字符串等.1,haha.
  • 匿名变量
    string("123")
  • 返回string的函数或表达式
    相当于一个匿名变量
  • move()语义

但是不能接受变量,也就是不能接受左值

模板参数的右值引用形参

template <typename T>
void f5(T&&);

当函数是一个模板函数的时候,当他的形参是右值引用的时候有如下的不同:

  • 传入左值,传入值的类型被推断为类型的引用
    比如,传入string类型,那么T被推断为string&

同时,引用折叠:怎么说,意思就是左值引用的引用就等于引用,也是是,所有的双数引用可以折叠为右值引用。
而所有单数的引用可以折叠为左值引用

T&& && &&=T&&
T&& && && & =T&

因此,综上棉量两点:
T = string &&是,传入的参数类型为string& &&,因此被折叠为string &
这就是模板函数的右值引用形参可以接受一个左值的原因。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容