当前位置: 首页 > news >正文

三 auto占位符

3.1 重新定义的auto关键字

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

int n = 5;
auto *pn = &n, m = 10;// 这里auto被推导为 int  所以int m = 10;合理
auto *pns = &n, m = 10.0;//编译失败,声明类型不统一

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

auto i = true ? 5 : 8.0; // i的数据类型为double

3.虽然C++11标准已经支持在声明成员变量时初始化(见第8章),但是auto却无法在这种情况下声明非静态成员变量

struct sometype {
auto i = 5; // 错误,无法编译通过
}struct sometype {
static const auto i = 5;
};//这个样子可以 但是i就是常量了 C++17修改
struct sometype {
static inline auto i = 5;
};

4.按照C++20之前的标准,无法在函数形参列表中使用auto声明形参(注意,在C++14中,auto可以为lambda表达式声明形参):

3.2 推导规则

1.在进行值传递的时候忽略原始的CV限定

const int i = 5;
auto j = i;         // auto推导类型为int,而非const int
auto &m = i;         // auto推导类型为const int,m推导类型为const int&
auto *k = i;         // auto推导类型为const int,k推导类型为const int*
const auto n = j;     // auto推导类型为int,n的类型为const int

2.使用auto声明变量初始化时,目标对象如果是引用,则引用属性会被忽略:

int i = 5;
int &j = i;
auto m = j; // auto推导类型为int,而非int&

3.使用auto和万能引用声明变量时(见第6章),对于左值会将auto推导为引用类型

int i = 5;
auto&& m = i; // auto推导类型为int& (这里涉及引用折叠的概念)
auto&& j = 5; // auto推导类型为int

根据规则3,因为i是一个左值,所以m的类型被推导为int&, auto被推导为int&,这其中用到了引用折叠的规则。而5是一个右值,因此j的类型被推导为int&&,auto被推导为int。
 

4.使用auto声明变量,如果目标对象是一个数组或者函数,则auto会被推导为对应的指针类型:
 

int i[5];
auto m = i; // auto推导类型为int*
int sum(int a1, int a2)
{return a1+a2;
}
auto j = sum // auto推导类型为int (__cdecl *)(int,int)

思考 

class Base {
public:virtual void f(){std::cout << "Base::f()" << std::endl;};
};
class Derived : public Base {
public:virtual void f() override{std::cout << "Derived::f()" << std::endl;};
};Base* d = new Derived();auto& b = *d;//auto b = *d;  b.f();

auto b  调用基类函数  auto& b调用子类的函数

个人认为的解释:*d的类型是确定的Base  auto b = *d; 那边auto就是推导出来的Base 所以调用的就是Base的f函数

而 auto&b  编译器推导出变量的类型时,会保留右值表达式的引用性 

右值 *d 的类型是 Base&,即 d 指向的 Derived 对象被解引用为 Base& 类型。
因此,b 的类型推导为 Base&(对 Base 的引用),实际引用的是 Derived 对象。

所以会调用Derived的f函数

3.3 什么时候使用auto
 

1.当一眼能看出类型的时候使用auto

一般是在遍历容器的时候使用 

    vector<int> x{ 1,2,3 };for (vector<int>::iterator it = x.begin(); it != x.end(); ++it){}//等价于for (auto = x.begin(); it != x.end(); ++it){}//当使用map的时候  对于这个容器遍历前面的 string应该为coonststd::map<std::string, int> str2int;//这个可以不加constfor (map< std::string, int>::iterator it = str2int.begin(); it != str2int.end(); ++it){cout << it->second << endl;}//这个得加for (pair<const string,int> &it : str2int){cout << it.second << endl;}

2.用于lambda 与bind 

auto l = [](int a1, int a2) { return a1 + a2; };
int sum(int a1, int a2) { return a1 + a2; };

auto b = std::bind(sum, 5, std::placeholders::_1);
 

3.4 返回类型推导
 

C++14标准支持对返回类型声明为auto的推导
 

auto sum(int a1, int a2) { return a1 + a2; };

如果有多个返回值 要返回值的类型一致

不同的返回类型会导致编译失败。

3.5lambda表达式中使用auto类型推导

在C++14标准中我们还可以把auto写到lambda表达式的形参中,这样就得到了一个泛型的lambda表达式
 

auto l = [](auto a1, auto a2) { return a1 + a2; };
auto retval = l(5, 5.0);
//在上面的代码中a1被推导为int类型,a2被推导为double类型,返回值retval被推导为double类型。

返回auto引用的方法

auto l = [](int &i)->auto& { return i; };
auto x1 = 5;
auto &x2 = l(x1);
assert(&x1 == &x2); // 有相同的内存地址

3.6 非类型模板形参占位符
 

c++17引入 它可以作为非类型模板形参的占位符

#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
}

c++17才有 


http://www.mrgr.cn/news/31402.html

相关文章:

  • Vue3中el-table组件实现分页,多选以及回显
  • 【Redis入门到精通三】Redis核心数据类型(List,Set)详解
  • 【Linux】进程概念
  • Zookeeper安装使用教程
  • JAVA8新特性——Optional
  • uboot:源码分析-启动第一阶段-start.S解析
  • IPD流程体系:IPD在硬件产品开发中的应用
  • NCNN 学习(2)-Mat
  • 嵌入式linux系统中rk3588芯片引脚基本操作
  • 基于SpringBoot的旅游管理系统
  • Linux:Bash中的文件描述符
  • Ansbile-变量
  • 【云网络】软件定义网络SDN的概念与应用(以PVE8用户隔离,TLS证书介绍,自签证书等为例)
  • 服务器非法关闭后MySQL服务启动失败
  • 解决RabbitMQ设置TTL过期后不进入死信队列
  • 【数据结构】什么是二叉搜索(排序)树?
  • 二层、三层网络基本原理
  • 6.C++程序中的基本数据类型
  • A. Closest Point
  • 基于开源鸿蒙(OpenHarmony)的【智能家居综合应用】系统