Last Updated on 2020年4月14日
数组类型和函数类型
尽管在大部分场合中,数组类型和函数类型都被转换成某种指针使用,然而它们确实是某种类型.
这一点在类型推导中很重要,因为类型推导可以推导出数组类型/函数类型
- 称
T[N]
型对象为数组类型,其中N必须为constexpr
,称T array[N]
中的array
为T[N]
型的一个实例.N
是数组的一个属性,当N
不同时,是不同类型的数组.
- 数组类型变量可以被隐式转换为指向数组首元素的指针.
- 转换为指针后,长度信息就丢失了.
- 在
T[N]
做函数形参时,编译器一定会将形参转换为指针,从而可以接受长度不同的数组,长度信息也随之丢失.
- 数组的长度信息未丢失时,编译器及用户是可以获取到这些长度信息的.
sizeof(array)/sizeof(array[0])
就是元素数量. - 可以使用引用型形参来保留数组的长度信息,对于模板,还可以使用自动推断.
- 自动推断:
template<class T>fun(T &);
或template<class T,int N>fun(T (&array)[N])
- 手动声明:
fun(int (&array)[100])
- 自动推断:
&array
类型是指向数组的指针,为T[N] *
型.retType (arg1Type,arg2Type...)
这样的类型称为函数类型.称retType fun(arg1Type,...)
中的fun
为该类型的实例,后文中使用using FT= retType (arg1Type,arg2Type,...)
来表示函数类型.- 函数对象
FT fun
在使用中可能会隐式的退化为指针类型FT *
,例如FT * p = foo; FT * p2 = &foo
decltype和auto
类型推断相关的内容主要有decltype和auto,其中,auto是通过初始化进行推导,其行为和模板类型推断完全一致
decltype用于获得对象的精确类型.为了简化用法,仅应当对左值或左值表达式使用decltype,因为对右值的推断可能产生分歧参考Cppreference
decltype
- 当输入是一个对象时,推断出的类型一定和输入对象完全相同.
- 当输入是一个左值表达式时,推断的结果是一个引用,该引用可以精确绑定到输入表达式.
- 注意:decltype用于推断数组或函数时,不会推导出指针.对于数组
dectype<array> ar;
会创建一个新的数组,对于函数decltype<fun> f2;
会创建一个无法使用的未初始化的函数,decltype<fun> * fp;
则创建了一个函数指针 - decltype推断的结果是一个编译期可用的类型,可以用
<type_traits>
中的类型操作算法处理.例如remove_reference<decltype(*iter)>::type
就能推断出*iter
对应的类型,而不是引用
auto
auto和函数模板实参推断的行为完全一致,仅语法上形式不同,为了便于说明,本节仅用模板实参推断进行描述.
- 模板实参推断就是通过编译器推断
T
的具体内容.除T &&
外,推断出的RealT
肯定不包含引用. T
,推断结果不含const- 推断出的数组/函数会退化为指针
T &
,推断结果可以包含constconst T &
的推断结果肯定不含const
- 推断出的数组/函数不会退化为指针
T &&
时,推断的结果必然包含引用,且可以包含const.- 用左值或左值表达式进行初始化时推断结果将为左值引用.
- 用右值初始化时,推导结果为右值引用.
// 注意:直接参与推导的部分必须是`T&&`形式的
// 这里的foo2并不是简单的`T&&`型, 这里直接参与推导的是`T`,是按照T的规则来推导的
template<class T>
void foo2(MyType<T>&& arg){
}
- 完美转发:将
T &&
和std::forward
配合即可
// 例如,对于`Relay(MyType())`,那么推导出的T就是`MyType &&`,此时`std::forward<T>(arg)`效果就相当于`static_cast<MyType &&>(arg)`
template<class T>
void Relay(T && arg){
bar(std::forward<T>(arg));
}
- 一般性举例
{
int raw;
int any
int &ref=raw;
auto b=ref;// auto为int;
auto &b1=ref;// auto为int;
decltype(ref) c=any;// decltype(ref) 为 int&
}
{
const int raw=0;
const int any=0;
const int &ref=raw;
auto b=ref;//auto为int
auto &b1=ref;//auto为const int
delcytple(ref) c=any;//delcytple(ref)为 const int&
}
int array[10]
auto p=array;//auto为 int*
auto &p=array;//auto为 int[10] &
decltype(array) a2;//等价为 int a2[10];