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

Effective C++: auto类型推断.

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1,请牢牢记住一点auto的推断其实是跟template的推断基本一致也有稍微的不同体现在std::initializer_list:

2,不能推断出一个模板中的另一个模板的类型(template<template<typenaem T> class A>);
 3, 当auto作为函数的参数类型或者返回类型的时候auto类型的推断规则无效!按照模板类型的推断规则来.

case 1: auto

 #include <iostream>
int main()
{
 int x = 27;
 int& xx = x;
 const int cx = x;
 const int& rx = x;
 
 auto n_ = 10; //auto = int;
 auto x_ = x; //auto = int;
 auto xx_ = x;//auto = int;
 xx_ = 100;
 std::cout<<x<<std::endl;
 auto cx_ = cx; //auto = int;
 auto rx_ = rx; //auto = int;
 
 cx_ = 10; //ok, but x is also 27.
 rx_ = 100;//as same sa above.
 
 
 return 0;
}

case 2:auto&

#include <iostream>
class Node{
 public:
  Node()=default;
  ~Node(){ std::cout<<"destroy"<<std::endl; }
};
int main()
{
 int x = 27;
 int& xx = x;
 const int cx = x;
 const int& rx = x;
 
 
 auto& x_ = x; //auto = int;
 x_ = 1;       //x = 1, now.
 std::cout<< x <<std::endl;
 
 auto& xx_ = x; //auto = int;
 xx_ = 2;
 std::cout<< xx_ <<std::endl;
 
 auto& cx_ = cx; //auto = const int;
 //cx_ = 3; //error.
 
 auto& rx_ = rx; //auto = const int;
 
 int* ptr = new int(2);
 //auto& p = &x; //error.
 auto& p =ptr; //p的类型是: int*(&); auto = int*; p是一个对ptr的引用. 
 *p = 10;
 std::cout<<p<<"  "<<ptr<<std::endl; //地址一样. 
 std::cout<<*p<<"  "<<*ptr<<std::endl;//数据一致. 
 delete ptr;
 
 int* ptr_two = new int(3);
 int* ptr_three = new int(4);
 std::cout<<ptr_two<<"  "<<ptr_three<<std::endl;
 
 auto& p_two = ptr_two;
 p_two = ptr_three; //现在ptr_two和p_two都指向了ptr_three. new int(3)还留在堆内!!内存泄漏了. 
 std::cout<<ptr_two<<"  "<<p_two<<std::endl;
 std::cout<<*ptr_two<<"  "<<*p_two<<std::endl;
 
 
 Node* ptr_node = new Node;
 auto& p_node = ptr_node;
 
 delete ptr_node;
 
 return 0;
}

case3: const auto

#include <iostream>
int main()
{
 int x = 27;
 const int cx = x;
 const int& rx = x;
 
 const auto y = 27; 
 const auto x_ = 2; //auto = int;
 const auto xx_ = x; //auto = int;
 const auto cx_ = cx; //auto = int;
 const auto rx_ = rx; //auto = int;
 
 int* ptr = new int(10);
 int* ptr_two = new int(20);
 const auto p = ptr;        //auto = int* , p的类型为int* const. 
 std::cout<<p<<"  "<<ptr<<std::endl;
 std::cout<<*p<<"  "<<*ptr<<std::endl;
 
 *p = 30;
 std::cout<<*p<<"  "<<*ptr<<std::endl;
 
 p = ptr_two; //error, p是一个顶层const. 
 
 delete ptr;
 delete ptr_two; 
 
 return 0;
}

case4: auto&&

 #include <iostream>
int main()
{
 int x = 27;
 const int cx = x;
 const int& rx = x;
 
 auto&& xx = 27; //auto = int;
 auto&& x_ = x; //auto = int&; 引用折叠 && + & = &; 
 x_ = 1;
 std::cout<< x <<std::endl;
 
 auto&& cx_ = cx; //auto = const int&; 引用折叠 && + & = &; 
 
 auto&& rx_ = rx; //auto = const int&; 同上. 
 
 return 0;
}

case 5: const auto&

#include <iostream>
int main()
{
 int x =27;
 const int cx = x;
 const int& rx = x;
 
 const auto& xx = 1; //auto = int;
 const auto& x_ = x; //auto = int;
 const auto& cx_ = cx; //auto = int;
 const auto& rx_ = rx; //auto = int;
 
 int* ptr = new int(10);
 int* ptr_two = new int(20);
 const auto& p = ptr; //ptr的类型是:int* const(&),auto = int*; p是一个对int* const类型的指针的引用!!!是引用!!!指针也能被引用!!.
 std::cout<<ptr<<"  "<<p<<std::endl;
 std::cout<<*ptr<<"  "<<*p<<std::endl;
 
 *p = 30;
 std::cout<<*ptr<<"  "<<*p<<std::endl;
 
 //p = ptr_two; //error, 这是一个顶层const 
 
 delete ptr;
 delete ptr_two;
 return 0;
}

case 6:数组和auto

#include <iostream>
int number_array[]{1, 2, 3};
int* arr = new int[3]{4, 5, 6};
const int* const ptr = nullptr;
int main()
{
 auto first = number_array; //auto = int* ;
 auto first_ = arr; //auto = int*;
 std::cout<<std::boolalpha<<std::is_same<int*, decltype(first)>::value<<" ";//输出: true.
 std::cout<<std::is_same<int*, decltype(first_)>::value<<std::endl;        //true.
  
 auto& second = number_array; //auto = int[3]; second的类型是 int (&)[3]. 
 auto& second_ = arr;          //auto = int*; second_的类型是int*(&); 
 std::cout<<std::boolalpha<<std::is_same<int(&)[3], decltype(second)>::value<<" ";//true
 std::cout<<std::is_same<int* (&), decltype(second_)>::value<<std::endl;         //true
 
 auto&& third = number_array; //auto = int(&)[3]; third的类型是 int(&)[3]. 
 auto&& third_ = arr;         //auto = int*(&);   third_的类型是 int*(&);
 std::cout<<std::boolalpha<<std::is_same<int(&)[3], decltype(third)>::value<<" ";//true
 std::cout<<std::is_same<int* (&), decltype(third_)>::value<<std::endl;         //true
 
 const auto forth = number_array; //auto = int*; forth的类型为: int* const,一个顶层const的指针. 
 const auto forth_ = arr;         //auto = int*; forth_的类型为: int* const,顶层const. 
 std::cout<<std::boolalpha<<std::is_same<int* const, decltype(forth)>::value<<" "; //true 
 std::cout<<std::is_same<int* const, decltype(forth_)>::value<<std::endl;         //true
 
 const auto& fifth = number_array; //auto = int[3]; fifth的类型为 const int(&)[3];
 const auto& fifth_ = arr;         //auto = int*; fifth的类型为 int* (&) const; 
 std::cout<<std::boolalpha<<std::is_same<const int(&)[3], decltype(fifth)>::value<<" ";//true
 std::cout<<std::is_same<int* const(&), decltype(fifth_)>::value<<std::endl;          //true
 
 
 
 return 0;
}

case 7: 函数和auto

 #include <iostream>
void function(const int& a, const int& b)
{
 std::cout<<a<<"  "<<b<<std::endl;
}
int main()
{
 auto func = function; //void (*)(const int&, const int&);
 (*func)(2, 0); 
 
 auto& func1 = function; //void (const int&, const int&);
 func1(3, 4);
 
 return 0;
}

看了这么多是不是发现其实跟模板类型推断一样呢?那么让我们来深入吧:

//c++提供了我们多种赋值的方式.
int a = 1;
int a(1);
int a{3};
int a={2};

但是我们用auto的话呢?

auto a = 1; //auto = int;
auto b(1); //auto = int;
auto c{3}; //auto = std::initializer_list<int>;
auto d={4}; //auto = std::initializer_list<int>;

还有:

auto list{1, 2, 3.0}; 
//error,竟然错了因为auto的类型被推断为std::initializer_list<int>但是3.0是一个float.

template<typename T>
void function(T param)
{ ...}

f({1, 2, 3}); //error!!!!!!!!
//由此我们可以看出不能推断出一个模板中的另一个模板的类型.

auto createInitList() //error, 这里竟然是和模板类型的推断规则一致的.
{
  return {1, 2, 3};
 }
 
 
 
 std::vector<int> v;
 auto resetV= [&v](const auto& newV){ v = newV; }
 
 resetV({1, 2, 4}); //error,这里相当于是reset(const T& newV),用的也是模板类型的推断规则.

关于尾至返回类型:

 #include <iostream>
#include <vector>
template<typename Container, typename Index>
auto function(Container& container, const Index& index)->decltype(container[index])
//如果使用了尾置返回类型auto是不会做任何事情的,其类型推断还是主要来自于decltype.
//由于std::vector的T& operator[](index),返回的是一个引用所以decltype推断出的类型也是一个引用. 
{
 return container[index];
}
int main()
{
 std::vector<int> v{1};
 function(v, 0)=2;
 
 std::cout<<v[0]<<std::endl; //输出为2. 
 
 return 0;
}

 错误的使用:

auto x; //error,不能知道x的类型.

int x1 = 10;
auto& ptr = &x1; //error.

 

语法(C++14):

decltype(auto) variable initializer  	(since C++14)
decltype(auto) function                 (since c++14)

针对: decltype(auto) function我们可以:

decltype(auto) function(int x, int y)

{

  return (x+y); //其实相当于调用 auto function(int x, int y)->decltype(x+y)

}

 

If the declared type of the variable is decltype(auto), the keyword auto is replaced with the expression (or expression list) of its initializer, and the actual type is deduced using the rules for decltype.

针对: decltype(auto) variable initializer我们可以:

decltype(auto) i =10; //i的类型为 int;

int x=10;

decltype(auto) y=(x); //相当于decltype((x)) y = x; 因此y的类型为 int&.

decltype(auto) list={1, 2}; //error, 因为{1, 2}不是表达式.

auto list_={1, 2}; //ok!

参考: https://my.oschina.net/u/2516597/blog/538605

 

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/650058

相关文章:

  • 利用CSS-border属性实现圆饼图表
  • 大圣归来:我们心中缺少一份英雄主义
  • Java命令学习系列(7):Javap(转)
  • 用VS2010编C#程序扫盲
  • 微软宣布Visual Studio 2015后继版本,开发者可以使用Visual C++ for Linux了
  • fullPage.js全屏滚动插件 中文帮助文档API
  • 9个 SSH常用命令选项(转载)
  • 二叉树的操作
  • jquery 的队列queue
  • CentOS下载
  • 开始学习第一天
  • 电梯演讲
  • Linux kernel Makefile for ctags
  • SVN之 trunk, branches and tags意义
  • Android Java执行Shell命令
  • [译]如何构建服务器端web组件,为何要构建?
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • 77. Combinations
  • Angular2开发踩坑系列-生产环境编译
  • exports和module.exports
  • Idea+maven+scala构建包并在spark on yarn 运行
  • JavaScript的使用你知道几种?(上)
  • Redis 中的布隆过滤器
  • Spring框架之我见(三)——IOC、AOP
  • spring学习第二天
  • VuePress 静态网站生成
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 使用docker-compose进行多节点部署
  • 使用Gradle第一次构建Java程序
  • 双管齐下,VMware的容器新战略
  • 思否第一天
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • # Apache SeaTunnel 究竟是什么?
  • #每天一道面试题# 什么是MySQL的回表查询
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • (1)STL算法之遍历容器
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (JS基础)String 类型
  • (SpringBoot)第七章:SpringBoot日志文件
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (黑马C++)L06 重载与继承
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (转)大道至简,职场上做人做事做管理
  • (转)原始图像数据和PDF中的图像数据
  • (转载)CentOS查看系统信息|CentOS查看命令
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET6 命令行启动及发布单个Exe文件
  • .net生成的类,跨工程调用显示注释
  • .net实现客户区延伸至至非客户区