C++11新特性之auto
- auto的使用
c++11引入了auto类型说明符,auto让编译器通过初始值来推算变量的类型,所以auto定义的变量必须有初始值。
使用auto也能在一条语句中声明多个变量,因为一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一样: - eg: auto i=0,*p=& i; //正确 auto sz=0,pi=3.14;//错误,sz和pi的类型不一样。
范围for循环,遍历给定序列中的每个元素并对序列中的每个值执行某种操作。 for(declaration:expression)statement
expression 部分是一个对象,用于表示一个序列,declaration部分负责定义一个变量,该变量被用于访问序列中的基础元素,每次迭代declaration部分的变量会被初始化为expression部分的下一个元素值。
范围for循环有两种用法:可以遍历字符串,数组,map,vector等容器。
string s("hello,world");
decltype(s.size()) punct_cnt=;//decltype也是c++11特性,用于选择和返回操作数的数据类型。
for(auto c:s)//对于s中的每个字符
if(ispunct(c))
++punct_cnt;string s("hello,world");
for(auto &c:s);//对于s中的每个字符,c是一个引用,赋值语句将会改变s中字符的值
c=toupper(c);
cout<<s<<endl;
正文
前言
本文的内容已经不新鲜了。关于auto,翻来覆去被人知道的都是这些东西,本文并没有提出新颖的auto用法。
本人原是痛恨博客一篇篇都是copy而来缺乏新意的探索,当然,本文不是copy而来,但发布这样一篇大家皆知的文章心里甚是惶恐。
本文对auto的内容加以整理,权当是自己的复习笔记了。C++98 auto
早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期:
int a =10 ; //拥有自动生命期
auto int b = 20 ;//拥有自动生命期
static int c = 30 ;//延长了生命期C++98中的auto多余且极少使用,C++11已经删除了这一用法,取而代之的是全新的auto:变量的自动类型推断。
C++11 auto
auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype。举个例子:
int a = 10;
auto au_a = a;//自动类型推断,au_a为int类型
cout << typeid(au_a).name() << endl;typeid运算符可以输出变量的类型。程序的运行结果输出了
int
这种用法就类似于C#或java中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。而是否会造成编译期的时间消耗,我认为是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。
auto的用法
上面举的这个例子很简单,在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。下面列举auto关键字的正确用法。
用于代替冗长复杂、变量使用范围专一的变量声明。
想象一下在没有auto的时候,我们操作标准库时经常需要这样:
#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
{
//...
}
}这样看代码写代码实在烦得很。有人可能会说为何不直接使用using namespace std,这样代码可以短一点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。使用auto能简化代码:
#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (auto i = vs.begin(); i != vs.end(); i++)
{
//..
}
}for循环中的i将在编译时自动推导其类型,而不用我们显式去定义那长长的一串。
在定义模板函数时,用于声明依赖模板参数的变量类型。
template <typename _Tx,typename _Ty>
void Multiply(_Tx x, _Ty y)
{
auto v = x*y;
std::cout << v;
}若不使用auto变量来声明v,那这个函数就难定义啦,不到编译的时候,谁知道x*y的真正类型是什么呢?
模板函数依赖于模板参数的返回值
template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
{
return x*y;
}当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从知道返回值的类型,这时我们可以使用auto。格式如上所示。
decltype操作符用于查询表达式的数据类型,也是C++11标准引入的新的运算符,其目的也是解决泛型编程中有些类型由模板参数决定,而难以表示它的问题。
auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的decltype(_Tx*_Ty)。为何要将返回值后置呢?如果没有后置,则函数声明时为:decltype(_Tx*_Ty)multiply(_Tx x, _Ty y)而此时_Tx,_Ty还没声明呢,编译无法通过。
注意事项
- auto 变量必须在定义时初始化,这类似于const关键字。
定义在一个auto序列的变量必须始终推导成同一类型。例如:
auto a4 = 10, a5 = 20, a6 = 30;//正确
auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型使用auto关键字做类型自动推导时,依次施加一下规则:
如果初始化表达式是引用,则去除引用语义。
int a = 10;
int &b = a; auto c = b;//c的类型为int而非int&(去除引用)
auto &d = b;//此时c的类型才为int& c = 100;//a =10;
d = 100;//a =100;如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。
const int a1 = 10;
auto b1= a1; //b1的类型为int而非const int(去除const)
const auto c1 = a1;//此时c1的类型为const int
b1 = 100;//合法
c1 = 100;//非法如果auto关键字带上&号,则不去除const语意。
const int a2 = 10;
auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
b2 = 10; //非法这是因为如何去掉了const,则b2为a2的非const引用,通过b2可以改变a2的值,则显然是不合理的。
初始化表达式为数组时,auto关键字推导类型为指针。
int a3[3] = { 1, 2, 3 };
auto b3 = a3;
cout << typeid(b3).name() << endl;程序将输出
int *
若表达式为数组且auto带上&,则推导类型为数组类型。
int a7[3] = { 1, 2, 3 };
auto & b7 = a7;
cout << typeid(b7).name() << endl;程序输出
int [3]
函数或者模板参数不能被声明为auto
void func(auto a) //错误
{
//...
}时刻要注意auto并不是一个真正的类型。
auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或者typeid。cout << sizeof(auto) << endl;//错误
cout << typeid(auto).name() << endl;//错误
C++11新特性之auto的更多相关文章
- C++ 11 新特性: auto 和 decltype 区别和联系
一. auto简介编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题,C++11新标准就 ...
- C++11新特性之三——auto
C++11中引入的auto主要有两种用途:自动类型推断和返回值占位.auto在C++98中的标识临时变量的语义,由于使用极少且多余,在C++11中已被删除.前后两个标准的auto,完全是两个概念 1. ...
- 【C++11新特性】 auto关键字
原文链接: http://blog.csdn.net/xiejingfa/article/details/50469045 熟悉脚本语言的人都知道,很多脚本语言都引入了“类型自动推断”技术:比如pyt ...
- C++11新特性— auto 和 decltype 区别和联系
一. auto简介 编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题,C++11新标准 ...
- C++11新特性总结 (二)
1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...
- C++11新特性总结 (一)
1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...
- C++ 11 新特性
C++11新特性: 1.auto 2.nullptr 3.for 4.lambda表达式 5.override ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- 在C++98基础上学习C++11新特性
自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...
随机推荐
- hotplug_uevent机制_修改mdev配置支持U盘自动挂载学习笔记
1.接入U盘,看输出打印信息并分析 (1)输出信息 自动创建设备节点 (2)用ls命令查看 这里/dev/sda表示整个U盘,/dev/sda1表示这个U盘的第一个分区. (3)手动挂载,查看文件,手 ...
- Druid.io系列(三): Druid集群节点
原文链接: https://blog.csdn.net/njpjsoftdev/article/details/52955937 1 Historical Node Historical Node的职 ...
- Running command-line BLAST
Ubuntu安装BLAST 2014-02-09 10:45:03| 分类: Linux/Ubuntu|举报|字号 订阅 下载LOFTER我的照片书 | very easy! su ...
- 版本控制git之二-分支
有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出. 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量, ...
- Java--神奇的hashcode
一.Object的HashCode定义 public native int hashCode(); Object类的hashCode方式使用了native修饰也就意味着真正的实现调用的其他语言编写的方 ...
- NodeJs中require use get typescript及其他知识点集合
NodeJs的Express使用 nodejs事件的监听与事件的触发 TypeScript学习笔记 深入浅出Node.js Nodejs开发Office插件 类百度文库文档上传.转换和展示功能项目开源 ...
- leetcode8
public class Solution { public int MyAtoi(string str) { , sign = , total = ; //1. Empty string ) { ; ...
- Oracle11gr2_ADG管理之switchover补充
之前演示的switchver总是提示下面的错误,并且需要人工干预: Oracle11gr2_ADG管理之switchover实战 DGMGRL> switchover to snewtest; ...
- javaWeb 开发的成长路线
感觉最近技术到了一个瓶颈,好长时间没有感觉进步了,本着活到老学到老的态度,笔者就去逛了下,看看前辈们写的文章,觉得他们写的非常不错,在这里特别贴出一张特别值得收藏的图片,不是说其他总结的图片不值得收藏 ...
- 使用jxl 解析Excel
jxl(Java Excel API) 使用方法 [1] 构建Workbook对象, 只读Workbook对象 // 直接从本地文档创建Workbook // 从输入流创建Workb ...