C++11 auto 和decltype的使用

auto

C++编程时,常常需要把表达式的值赋给变量,需要在声明变量的时候清楚的知道变量是什么类型。然而做到这一点并非那么容易,有时候根本做不到。为了解决这个问题,C++11新标准就引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应某种特定的类型说明符(例如 int)不同。auto 让编译器通过初始值来进行类型推演。从而获得定义变量的类型,所以说 auto 定义的变量必须有初始值。如下所示:

auto i; // error: declaration of variable 't' with deduced type 'auto' requires an initializer
//因此我们在使用auto时,必须对该变量进行初始化。

auto i= 0; //0为int类型,auto自动推导出int类型
auto j = 2.0; //auto 自动推导出类型为float

int a = 0;
auto b = a; //a 为int类型
auto &c = a; //c为a的引用
auto *d = &a; //d为a的指针
auto i = 1, b = "hello World"; //error: 'auto' deduced as 'int' in declaration of 'i' and deduced as 'const char *' in declaration of 'b'

/* auto 作为成员变量的使用*/
class test_A
{
    
    
public:
    test_A() {
    
    }
    auto a = 0; //error: 'auto' not allowed in non-static class member
    static auto b = 0; //error: non-const static data member must be initialized out of line
    static const auto c = 0;
};

/*c11 中的使用*/
auto func = [&] {
    
    
    cout << "xxx";
}; 
// 不关心lambda表达式究竟是什么类型
auto asyncfunc = std::async(std::launch::async, func);
// 懒得写std::futurexxx等代码

auto使用的限制

  1. auto的使用必须马上初始化,否则无法推导出类型
  2. auto在一行定义多个变量时,各个变量的推导不能产生二义性,否则编译失败
  3. auto不能用作函数参数
  4. 在类中auto不能用作非静态成员变量
  5. auto不能定义数组,可以定义指针
  6. auto无法推导出模板参数

auto 的推导规则

  1. 在不声明为引用或指针时,auto会忽略等号右边的引用类型和const、volatile限定
  2. 在声明为引用或者指针时,auto会保留等号右边的引用和const、volatile属性
    const int a = 0;
    auto b = a;
    auto &c = a;
    c = 3; 
    //error: cannot assign to variable 'c' with const-qualified type 'const int &'
    //note: variable 'c' declared const here

decltype

decltype用于推导表达式类型,这里只用于编译器分析表达式的类型,表达式实际不会进行运算

int fun(){
    
     return 0; }
decltype(fun()) a;
decltype(fun()) b = 5;

int fun2(int a){
    
     return 0; }
int c = 0;
decltype(fun2(c)) a;
decltype(fun2(c)) b = 5;

注意:decltype不会像auto一样忽略引用和const、volatile属性,decltype会保留表达式的引用和const、volatile属性

decltype 的推导规则

对于decltype(exp)有:

  1. exp是表达式,decltype(exp)和exp类型相同
  2. exp是函数调用,decltype(exp)和函数返回值类型相同
  3. 其它情况,若exp是左值,decltype(exp)是exp类型的左值引用
int a = 0, b = 0;
decltype(a + b) c = 0; // c是int,因为(a+b)返回一个右值
decltype(a += b) d = c;// d是int&,因为(a+=b)返回一个左值

d = 20;
cout << "c " << c << endl; // 输出c 20

auto和decltype的配合使用

auto和decltype一般配合使用在推导函数返回值的类型问题上。事例如下:

template<typename , typename U>
return_value add(T t, U u) {
    
     
    // t和v类型不确定,无法推导出return_value类型
    return t + u;
}

上面代码由于t和u类型不确定,那如何推导出返回值类型呢,我们可能会想到这种

template<typename T, typename U>
decltype(t + u) add(T t, U u) {
    
     
    // t和u尚未定义
    return t + u;
}

这段代码在C++11上是编译不过的,因为在decltype(t +u)推导时,t和u尚未定义,就会编译出错,所以有了下面的叫做返回类型后置的配合使用方法:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    
    
    return t + u;
}

返回值后置类型语法就是为了解决函数返回值类型依赖于参数但却难以确定返回值类型的问题。

猜你喜欢

转载自blog.csdn.net/CFH1021/article/details/106448303