C++11~20新特性:类型推导

学习整理自https://download.csdn.net/download/monkeylee2011/62474922

目录

一. auto占位符

1.1. 推导规则

1.2. 使用注意

二. decltype说明符

2.1. 推导规则

2.2. decltype的用处

2.3. decltype(auto)

2.4. auto & decltype 区别


一. auto占位符

        C++11引入:auto,用来声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。代码示例:

auto num = 5; //推到为 int 类型
auto str = "hello world"; //推到为const char* 类型
auto = add(int a,int b)->int  //返回类型后置,auto为返回值占位符
{
    return a + b;
}

1.1. 推导规则

        (1)如果auto声明的变量是按值初始化,即声明时没有使用引用或指针,则推导出的类型忽略const、volatile限定符。代码示例:

const int i = 10;
auto j = i; //auto推导类型为int,而非const int,const属性忽略
auto &m = i;//含引用,auto推导类型为const int,m推导类型为const int&,const属性保留
auto *k = i;//含指针,auto推导类型为const int,k推导类型为const int*,const属性保留

        (2)使用auto声明变量初始化时,若目标对象是引用,则引用属性被忽略。代码示例:

int ii = 9;
int &j = i;
auto k = j; //auto 推导类型为int,而非int&, 引用属性被忽略

        (3)使用auto和万能引用声明变量时,对于左值会将auto推导为引用类型。 代码示例:

int i = 1;
auto &&j = i;//i是左值,auto被推导为int&,j推导为int&
auto &&m = 5;//5是右值,auto被推导为int,m被推导为int&&

        (4)使用auto声明变量,若目标对象是一个数组或函数,则auto被推导为对应的指针类型。代码示例:

int ch[5];
auto mm = ch; //mm被推导为int*

int sum(int a,int b) {return a+b;}
auto j =sum; //j被推导为int(__cdecl*)(int ,int)

        (5)C++17标准:使用auto与列表初始化组合时,

        直接使用列表初始化,列表中必须是单元素,auto类型被推导为单元素类型;

        用等号加列表初始化,列表中可单元素可多元素,auto类型被推导std::initializer_list<T>,T是元素类型。在列表中包含多个元素的时候,元素的类型必须相同,否则编译器会报错。

auto x1 = { 1, 2 }; // x1类型为 std::initializer_list<int>
auto x2 = { 1, 2.0 }; //编译失败,花括号中元素类型不同
auto x3{ 1, 2 }; // 编译失败,不是单个元素
auto x4 = { 3 }; // x4类型为std::initializer_list<int>
auto x5{ 3 }; // x5类型为int

1.2. 使用注意

        (1)使用auto占位符声明变量的时候必须初始化变量

        (2)当用一个auto关键字声明多个变量的时候,编译器遵从由左往右的推导规则,以最左边的表达式推断auto的具体类型:

int m = 10;
auto *n = &m, i = 10;//&m的类型时int*,所以n的类型推导为int*,auto推导为int,所以i被推导为int

        (3)当使用条件表达式初始化auto声明的变量时,编译器总是使用表达能力更强的类型:

atuo bo = true ? 5:10.0;//bo被推导为double

        (4)C++11标准中静态成员变量可以用auto声明并且初始化,不过前提是auto必须使用const限定符(非静态成员变量不允许使用auto):

struct sample{
    static const auto num = 5;
}

        (5)C++17标准中,对于静态成员变量,auto可以在没有const的情况下使用

        (6)C++17标准中,可将auto作为非类型模板形参的占位符:

#include <iostream>
template<auto N>
void f()
{
 std::cout << N << std::endl;
}
int main()
{
 f<5>(); // N为int类型
 f<'c'>(); // N为char类型
 f<5.0>(); // 编译失败,非类型模板参数不能为double
}

        (7)C++14标准中,可将auto写到lambda表达式的形参中,得到一个泛型的lambda表达式:

auto l = [](auto a1, auto a2) { return a1 + a2; };//a1被推导为int,a2被推导为double
auto retval = l(5, 5.0);//retval被推导为double

        (8)C++14标准中,可将函数返回值类型声明为auto的推导

auto sum(int a1, int a2) { return a1 + a2; }//返回类型被推导为int型

        (9)C++20标准中,可在函数形参列表中使用auto声明形参。

void Sample(auto str){...} //c++20编译通过,c++20之前编译失败

二. decltype说明符

        C++11标准:引入decltype说明符,作用:可以获取对象或者表达式的类型。

        使用方法:decltype(表达式)

        特点:

        (1)decltype的自动类型推断发生在编译期(和auto一样)

        (2)decltype不会真正计算表达式的值

      【注意】:保证表达式的结果是有类型的,不能是 void,否则编译出错。

2.1. 推导规则

decltype(e)(其中e的类型为T)的推导规则:

        (1)如果e是一个未加括号的标识符表达式(结构化绑定除外)或者未加括号的类成员访问,则decltype(e)推断出的类型是e的类型T。

        (2)如果e是一个函数调用或者仿函数调用,那么decltype(e)推断出的类型是其返回值的类型。

        (3)如果e是一个类型为T的左值,或者被括号( )包围,则decltype(e)是T&。

        (4)如果e是一个类型为T的将亡值,则decltype(e)是T&&。

        (5)除去以上情况,则decltype(e)是T。

        (6)通常情况下,decltype(e)所推导的类型会同步e的const/dvolatile限定符,但当e是未加括号的成员变量时,父对象表达式的cv限定符会被忽略,不能同步到推导结果。如下举例中decltype(a->x)

const int&& foo();
int i;
int n[10];
struct A 
{
    double x;
};
const A* a = new A();

decltype(foo()); // 推导类型为const int&&, 满足规则(2)
decltype(i); // 推导类型为int,满足规则(1)
decltype(a->x); // 推导类型为double,满足规则(1)
decltype((a->x)); // 推导类型为const double&,加了括号,不适用规则(1),因a->x是一个左值,故...
decltype(n[5]); //推导类型为int&,n[5]返回的是数组中第6个元素,是一个左值 ,满足规则(3)

2.2. decltype的用处

        C++11中,decltype的主要用于声明模板函数,此模板函数的返回值类型依赖于其参数类型.

2.3. decltype(auto)

        C++14引入:decltype(auto)这个结合体。作用就是告诉编译器用decltype的推导表达式规则来推导auto。

        C++17标准中decltype(auto)也能作为非类型模板形参的占位符。

#include <iostream>

template<decltype(auto) N>
void f()
{
     std::cout << N << std::endl;
}
static const int x = 11;
static int y = 7;
int main()
{
     f<x>();     // N为const int类型
     f<(x)>();   // N为const int&类型
     f<y>();     // 编译错误,因为y不是一个常量,编译器无法对函数模板实例化
     f<(y)>();   // N为int&类型,因为(y)被推导为引用类型,恰好对于静态对象而言内存地址是固定的,所以可以顺利地通过编译
}

2.4. auto & decltype 区别

        (1)auto不能在非静态成员变量中使用,decltype可以:

struct S1 {
     int x1;
     decltype(x1) x2;
     double x3;
     decltype(x2 + x3) x4;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值