自动类型推导

在c++11中我们可以使用 auto自动推导变量的类型,还可以结合declttype来表示函数的返回值

一、auto关键字

(一)auto的推导规则

在c++11中auto并不代表一种实际的数据类型只是一个类型声明的"占位符"

  • auto在使用时必须对auto声明的变量初始化,从而让编译器推导出他的示例类型,在编译时自动将auto替换为真正的数据类型

auto 变量名 = 变量值;

#include <iostream>
using namespace std;
void test(){
    auto x=10;
    auto y="hello world";
    auto z=true;
    cout<<typeid(x).name()<<endl;
    cout<<typeid(y).name()<<endl;
    cout<<typeid(z).name()<<endl;
    int temp =20;
    auto *a = &temp;
    auto b=&temp;
    cout<<typeid(a).name()<<endl;
    cout<<typeid(b).name()<<endl;
}


int main() {
    test();
    system("pause");
    return 0;
}

  • auto可以和指针、引用结合起来使用 也可以带上 const 、volatile限定符
    • 当变量不是指针或者引用类型时,推导的结果不会保留 const volatile关键字
    • 当变量是指针或者引用类型时,推导的结果会保留 const volatile关键字
int tmp = 250;
const auto a1 = tmp; //const int*
auto a2 = a1;
const auto &a3 = tmp;//const int*
auto &a4 = a3;  //const int*
/*变量a1的数据类型为 const int,因此auto关键字被推导为 int类型
变量a2的数据类型为 int,但是a2没有声明为指针或引用因此 const属性被去掉, auto被推导为 int
变量a3的数据类型为 const int&,a3被声明为引用因此 const属性被保留,auto关键字被推导为 int类型
变量a4的数据类型为 const int&,a4被声明为引用因此 const属性被保留,auto关键字被推导为 const int类型*/


(二)auto的限制

  • 不能作为函数的参数使用。因为只有在函数调用的时候才会给函数参数传递参数,auto要求必须给修饰的变量赋值,因此二者矛盾。
  • 不能用于类的非静态成员变量的初始化(类的非静态成员是不属于类的是属于实例化对象的)
  • 不能使用auto关键字定于数组
  • 无法使用auto推导出模板参数

(三)auto的应用

  • 用于STL容器的遍历
#include <iostream>
using namespace std;
#include <vector>
void test01(){
    vector<int>v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    for(auto it=v.begin();it!=v.end();it++){
        cout<<*it<<" ";
    }
    cout<<endl;
}


int main() {
    test01();
    system("pause");
    return 0;
}

  • 用于泛型编程
#include <iostream>
using namespace std;
class A1{
public:
    static int get(){
        return 100;
    }
};
class A2{
public:
    static string get(){
        return "我被调用了";
    }
};
template<typename T>
void function( ){
    auto val =T::get();
    cout<<"val:"<<val<<endl;
}

int main() {
    function<A1>();
    function<A2>();
    system("pause");
    return 0;
}

二、decltype

在不需要或者不能定义变量,但是希望的到某种类型,这时候可以适应decltype关键字,它的作用是在编译器编译时推导出一个表达式的类型

语法:decltype (表达式) 

(一)基础用法

表达式为普通变量或者普通表达式或者类表达式,在这种情况下,使用decltype推导出来的类型哥表达式的类型是一致的。

#include <iostream>
using namespace std;

class Test
{
public:
    string text;
    static const int value = 1110;
};
void func(){
    int a = 100;
    decltype(a) b=99;
    decltype(a+1.2) c=101.2;
    decltype(a+b*c) d=1993.52;
    decltype(Test::value) e=666;
    cout<<"a:"<<a<<endl;
    cout<<"b:"<<b<<endl;
    cout<<"c:"<<c<<endl;
    cout<<"d:"<<d<<endl;
    cout<<"e:"<<e<<endl;
}
int main(){
    Test t;
    decltype(t.text) s="hello 666666";
    cout<<"s:"<<s<<endl;
    func();
    return 0;
}

(二)表达式是函数调用

表达式是函数调用,使用decltype推导出的类型和函数返回值一致

对于纯右值而言,只有类类型可以携带const、volatile限定符,除此之外需要忽略掉这两个限定符

class Test{...};
//函数声明
int func_int();                 // 返回值为 int
int& func_int_r();              // 返回值为 int&
int&& func_int_rr();            // 返回值为 int&&

const int func_cint();          // 返回值为 const int
const int& func_cint_r();       // 返回值为 const int&
const int&& func_cint_rr();     // 返回值为 const int&&

const Test func_ctest();        // 返回值为 const Test




int main()
{

    //decltype类型推导
    int n = 100;
    // a:int
    decltype(func_int()) a = 0;
    // b:int& 左值引用
    decltype(func_int_r()) b = n;
    // c:int&& 右值引用
    decltype(func_int_rr()) c = 0;
    // d: int 纯右值   ==》返回一个纯字面量 忽略 const
    decltype(func_cint())  d = 0;
    // e: const int& 左值引用
    decltype(func_cint_r())  e = n;
    // f: const int&& 右值引用
    decltype(func_cint_rr()) f = 0;
    // g: const Test 
    decltype(func_ctest()) g = Test();
    return 0;
}

(三)表达式是一个左值

表达式是一个左值,或者被()包围,使用decltype推导出的是表达式类型的引用(如果有 const,volatile 限定符不能忽略)

左值:可以取到地址,通常是变量

右值:取不到地址,通常是常量

#include <iostream>
using namespace std;

class Test
{
public:
    int a = 9;
    string text;
    static const int value = 10;

};

int main()
{
    const Test t;
    //带有括号的表达式
    decltype(t.a) a=0;  //a的类型为int
    decltype((t.a)) b =a; //b的类型为const int &

    //加法表达式
    int n =0,m=0;
    decltype(n+m) c = 0; //c的类型为int
    decltype(n=n+m) d = n; //d的类型为int & 
    cout<<"wangdefa"<<endl;
    return 0;    
}

(四)decltype在泛型编程中的使用举例

示例代码:

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

template<typename T>
class Container
{
public:
    void print(T& t)
    {
        for(m_it = t.begin(); m_it!= t.end(); ++m_it)
        {
            cout << *m_it << " ";
        }
    }


private:
    decltype(T().begin()) m_it;  //自动推导迭代器类型
};

int main()
{
    list<int> ls{1,2,3,4,5,6,7,8,9};
    Container<list<int>> c;
    c.print(ls);
    return 0;
}

(五)返回类型后置

参数类型后置方法:

// 符号 -> 后边跟随的是函数返回值的类型
auto func(参数1, 参数2, ...) -> decltype(参数表达式)
#include <iostream>
using namespace std;

template <typename T, typename U>
// 返回类型后置语法
auto add(T t, U u) -> decltype(t+u) 
{
    return t + u;
}

int main()
{
    int x = 520;
    double y = 13.14;
    auto z = add<int, double>(x, y);
    auto z = add(x, y);		// 简化之后的写法
    cout << "z: " << z << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值