面试题答案
一键面试- 调用
foo(10)
时:T
被推导为int
。因为foo
的参数param
是值传递,编译器会忽略传递值的顶层const
(如果有的话),10
是int
类型,所以T
推导为int
。
- 调用
bar(10)
时:T
被推导为int
。bar
的参数param
是const T&
,这里10
是右值int
类型,T
被推导为int
,然后param
成为const int&
类型,即对一个临时的const int
对象的引用。
- 调用
foo(num)
时:T
被推导为int
。同样因为foo
是值传递,编译器忽略num
的顶层const
,num
是const int
类型,但传递给foo
时,T
仍然推导为int
,param
会是int
类型的副本,丢弃了const
属性。
- 调用
bar(num)
时:T
被推导为int
。bar
的参数是const T&
,num
是const int
,T
推导为int
,param
成为const int&
,即对num
这个const int
对象的引用。
- 这种类型推导差异在模板参数使用
const
时的重要影响:- 值传递:在值传递的模板参数(如
foo
)中,顶层const
会被忽略,这意味着模板函数内部不能修改传入的const
对象,但函数会得到一个非const
的副本。这在性能上可能有影响,因为会创建副本,并且丢失了对象可能原本具有的const
语义。 - 引用传递:在引用传递的模板参数(如
bar
)中,const
是模板参数类型的一部分。这使得模板函数可以接受const
和非const
对象,并且能够保持对象的const
属性,避免意外修改对象,同时也避免了不必要的副本创建,提高了效率。如果需要在模板函数中保证对象的常量性并且避免副本开销,使用const T&
作为参数是更好的选择。
- 值传递:在值传递的模板参数(如