C++11类型推导

本文介绍了C++11中auto关键字的新功能,包括类型推断、指针引用的结合、常量和volatile属性的处理,以及auto在函数参数、成员变量、数组和模板参数中的限制。此外,还探讨了auto如何简化代码和处理不确定类型的场景。
摘要由CSDN通过智能技术生成

auto关键字的新意义

        下面看下auto的一些基本用法:

        auto x = 5;        //OK,x是int类型

        auto pi = new auto(1);        //OK,pi被推导为int *

        const auto* v = &x, u = 6;        //OK,v是const int* 类型,u是cosnt int 类型

        static auto y = 0.0;        //OK,y是double类型

        auto int r;        //error,auto不在表示存储类型指示符

        auto s;            //error,auto无法推导出s的类型

        在上面的代码实例中:字面量5是一个const int类型,变量x将被推导为int类型(const 被丢弃),并被初始化为5,pi的推导说明auto还可以用于new操作符。在上面例子中,new操作符后面的auto(1)被推导为int (1),因此pi的类型是int *;接着,由&x的类型是int *,推导出const auto* 中的auto应该是int,于是v被推导出为const int*,而u则被推导为const int。

        v和u的推导需要注意两点:

        虽然经过前面const auto* v = &x的推导,auto的类型可以确定为int了,但是u仍然必须要在后面写“=6”,否则编译器不予通过。

        u的初始化 不能使编译器推导产生二义性。例如,把u初始化改成“u = 6.0”,编译器将会报错。

        auto.cpp:20:8: error: inconsistent deduction for ‘auto’: ‘const int’ and then ‘const double’ const auto* v = &x, u = 6.0;

        auto并不能代表一个实际的类型声明,只是一个类型声明的“占位符”,所以auto s会报错。

        使用auto声明的变量必须马上初始化,以让编译器推断出它的实际类型,并在编译时将auto占位符替换为真正的类型。

auto的推导规则

        aut可以同指针,引用结合起来使用,还可以带上cv限定符(const和volatile限定符的统称)。

        int x = 0;

        auto * a = &x;       //a -> int*,auto被推导为int

        auto b = &x;          // b-> int*,auto被推导为int*

         auto &c = x;         //c -> int&,auto被推导为int

        auto d = c;            //d -> int,auto被推导为int

        const auto e = x;        // e -> const int 

        auto f =e;                //f -> int

        const auto& g = x;        //g -> const int& 

        auto& h = g;                //h -> const int&

        从上面的例子可以看出:

        a和c的推导结果是很显然的,auto在编译时被替换为int,因此a和c分别被推导为int* 和int &。

        b的推导结果说明,其实auto不声明为指针,也可以推导出指针类型。

        d的推导结果说明当表达式是一个引用类型时,auto会把引用类型抛弃,直接推导成原始类型int。

        e的推导结果说明,const auto会在编译时被替换为const int。

        f的推导结果说明,当表达式带有const(实际上volatile也会得到同样的结果)属性时,auto会把const属性抛弃掉,推导成non-const类型int。

        g,h的推导说明,当auto和引用(换成指针在这里也将得到同样的结果)结合时,auto的推导将保留表达式的const属性。

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

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

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

auto的限制

        auto 不能用于函数参数

        void func(auto a = 1){}        //error,auto不能用于函数参数

        

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

        struct Foo

        {

                auto var1 = 0;                //error:auto不能用于非静态成员变量

                static const auto var2 = 0; //OK:var2 -> static const int

        };



        auto 无法定义数组

        auto rr[10] = {1, 2,3};        //error:auto无法定义数组



        Bar<auto> bar;        //error:auto无法推导出模板参数

什么时候使用auto

        C++11之前,定义了一个stl容器后,在遍历的时候常常这样写代码:      

  map<int, int> m_map;

        map<int, int>::iterator it = m_map.begin();

         for(; it != m_map.end(); it++)

        {

                 //do something

         }

        观察上面的迭代器变量it的定义过程,要写很大一串。

        使用auto以后的语法:

        map<int, int> m_map;

        for(auto it = m_map.begin(); it != m_map.end(); it++)

        {

                // do something

         }

        再次观察it的定义过程,代码量少了

        另外,在很多情况下我们是无法知道变量应该被定义成什么类型,请看下面的代码清单:

#include <iostream>
#include <map>
using namespace std;

class Foo
{
public:
    static int get(void)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        return 0;
    }
};

class Bar
{
public:
    static const char* get(void)
    {
        printf("%s %s %d\n", __FILE__, __func__, __LINE__);
        return "0";
    }
};

template<class A>
void func(void)
{
    auto val = A::get();
}


int main()
{
    func<Foo>();
    func<Bar>();

    return 0;
}

        在这个例子里,我们希望定义一个泛型函数func,对所有具有静态get方法的类型A,在得到get的结果后能统一的后续处理。若不适用auto,就不得不对func再增加一个模板参数,并在外部调用时手动指定get的返回类型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值