类型推导(auto、decltype)

auto

一、auto类型推导(在推导时,不能使auto有二义性)

        auto定义的变量,可以根据初始化的值,在编译时推导出变量名的类型(auto必须初始化)

        对于系统来说12.23认为是double, 12.23f为float

int main()
{
    auto x=5;                //ok x是int类型
    auto pi = new auto(1);   //ok pi 被推导为int *;
    const auto *xp =&x ,u=6; //ok xp是const int*类型,u是const int类型
    static auto dx=0.0;      //ok dx是double类型
    auto int b;              //error C++11中auto不再表示存储类型指示符
    auto s;                  //error 没有初始化auto无法推导出s的类型
}
int main()
{
    auto x=5;
    auto *ip=&x,y=10;   //ip=>int*,y=>int auto=>int
    auto sp=&x,z=10;    //error  sp=>int* auto=>int*
                        //       z=>int auto=>int        此时出现二义性

   
    const auto *xp=&x,u;//error u没有初始化,auto必须初始化
    const auto *ip=&x,u=6;//ok
}
int main()
{
    const int x=10;
    auto xa=x;    //xa=>int 
    auto &ya=x;   //引用, ya=>const int &
    auto &za=10;//error 无法做到常性引用
}

二、auto的推导规则

        从上面的示例中可以看到auto的一些使用方法。它可以同指针、引用结合起来使用,还可以带上cv限定符。

int main()
{
    int x=0;
    auto *ip=&x;    //ok ip->int* ,auto被推导为int
    auto xp=&x;     //ok xp->int* ,auto被推导为int*
    
    auto &c=x;      //ok c->int & ,auto被推倒为int
    auto d=x;       //ok d->int, auto被推导为int

    const auto e=x; //ok e->const int;
    auto f=e;       //ok f->int;
    const auto &g=x;//ok g->const int &
    auto &h=g;      //ok h->const int &
}

int main()
{
    int a=10;
    const int* ip=&a;    //*ip不可变
    auto p=ip;           //p->const int* ,auto->const int* ,p=ip -> p=&a不可通过*p改变a的值
    auto& s=ip;          //s->const int*& ,auto->const int*
    
    int* const sp=&a;    //sp->&a 不可变,*sp可变
    auto p2=sp;          //p2->int*  p2=&b不会影响sp=&a
    auto& p3=sp;         //p3->int* const &
    return 0;
}

通过上面的一系列示例,可以得到下面这两条规则:

1.当不声明为指针或引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致

2.当声明为指针或引用时,auto的推导结果保持初始化表达式的cv属性。

三、auto作为函数的形参类型

void func(auto x)
{
    auto dx=12.23;    //此时x的auto与dx的auto无关,不会出现二义性
    cout<<sizeof(x)<<endl;
    cout<<typeid(x).name()<<endl;    //typeid(x).name输出的是x的类型名
}
int main()
{
    int a=10;
    int ar[]={12,23,34,45,56};
    func(a);    //sizeof=>4  typeid.name=>int
    func(ar);   //ar为首地址,sizeof=>4  typeid.name=>int *
}


void funr(auto &x)    //引用
{
    cout<<sizeof(x)<<endl;
    cout<<typeid(x).name()<<endl;  
}
int main()
{
    int a=10;
    int ar[]={12,23,34,45,56};
    funr(a);    //sizeof=>4   typeid.name=>int &
    funr(ar);   //sizeof=>20  typeid.name=>int [5]&
    //传地址  x为ar的别名同一地址空间,并不是首地址
}

注意:

sizeof(ar); int(&br)[10]=ar; int(*p)[10]=ar;

只有在这三种情况下ar代表数组整体,其他情况代表数组首地址。

四、auto限制

struct Foo
{
    auto value = 0;                //error:auto不能用于非静态成员变量
    static const int num = 10;     //ok:num->static const int;
}

int main()
{
    int ar[10]={0};
    auto br=ar;                //ok br->int*
    auto &cr=ar;               
    auto cr[10]=ar;            //error:auto无法定义数组
    auto dr[5]={1,2,3,4,5};    //error:auto无法定义数组
}

总结:

1.C++中auto成为类型指示符

2.auto不能用于函数参数

3.auto不能用于非静态成员变量

4.auto无法定义数组

5.实例化模板时不能使用auto作为模板参数

6.auto不能设计结构体

7.auto无法推导结构体变量类型(auto x{" ljl ",12};        //error无法确定那个结构体)

五、auto可以推导函数的返回类型

template<class T>
T my_max(T a,T b)
{
    return a>b?a:b;
}
int main()
{
    auto x=my_max(12,23);
    auto y=my_max('a','b');

    cout<<x<<endl;
    cout<<y<<enfl;
    return 0;
}

struct Student
{    
    char s_name[20];
    int s_age;
};

auto func()
{
    struct Student x{"ljl",12};
    return x;
}

decltype关键字

 一、decltype的几种形式

int main()
{
    int x=10;                //decltype(x) c; 可以不用初始化
    decltype(x) y=1;         //y->int
    decltype(x+y) z=0;       //z->int
    const int& i=x;
    decltype(i) j=y;         //有引用,要有初始值  j->const int&
    const decltype(z)* p=&z; //p->const int*  *p->const int
    decltype(z)* ip=&z;      //ip->int*    *ip->int
    decltype(ip)* pp=&ip;    //pp->int**  *pp->int*   **pp->int
    decltype(x+1) x1=x;        
    decltype(x+y) x2=x;
    decltype((x)) rx=x;      //rx=>int&
    return 0;
}

decltype可以抓取cv特性

int main()
{    
    int a=10;
    decltype(++a) ra=a;    //++a返回该变量的引用    ra->int&
    decltype(a++) rb=a;    //  ra->int
    //a不会被+1,只在意类型,不运行ra=10,rb=10;
}

二、函数表达式

int add(int a,int b)
{
    return a+b;
}

int main()
{
    int x=10,y=20;
    decltype(add(0,0)) z;    //z->int
    z=add(x,y);
}

三、decltype的推导规则

eg:decltype(exp)  varName

1.如果exp是一个不被括号()包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,decltype(exp)的类型和exp一致

2.如果exp是函数调用,则decltype(exp)的类型就和函数返回值的类型一样

3.如果exp是一个左值,或被括号()包围,decltype(exp)的类型就是exp的引用,假设exp的类型为T,则decltype(exp)的类型为T&

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值