Chinaunix首页 | 论坛 | 博客
  • 博客访问: 622444
  • 博文数量: 79
  • 博客积分: 848
  • 博客等级: 军士长
  • 技术积分: 1800
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 19:30
文章分类

全部博文(79)

文章存档

2015年(4)

2013年(39)

2012年(36)

分类: C/C++

2013-08-30 17:01:49

自从c11出来之后一直也没有很系统的学习一下里面的新的特性,现在准备开几篇博文来记录一下,大部分的东西是从官方文档中翻译过来的,如果英语比较好,还是建议大家去读官方的文档,水平有限,总结的可能有些拙劣,还望海涵!

首先对于auto关键字功能的一个扩充:

在了解新特性之前我们有必要再去总结一下,之前auto关键字的作用:
auto:用来声明自动变量。它是存储类型标识符,表明变量(自动)具有本地范围,块范围的变量声明(如for循环体内的变量声明)默认为auto存储类型。 其实大多普通声明方式声明的变量都是auto变量,他们不需要明确指定auto关键字,默认就是auto的了。auto变量在离开作用域是会变程序自动释放,不会发生内存溢出情况(除了包含指针的类)。使用auto变量的优势是不需要去考虑变量是否被释放,比较安全。
new:new是用来在堆上申请内存地址的关键字,他产生的变量不会自动释放,除非delete来手动释放,或者程序结束时由操作系统释放,使用new的优势是内存使用比较灵活,理论可以申请任意大小的内存区块(实际与操作系统有关),但这很容易产生问题,一不小心忘记释放对象,特别是在频繁调用的函数内创建的对象忘记释放时,会产生内存溢出,
严重时导致程序出错,系统崩溃。但是现在也有很多的方法避免这些问题,如智能指针,用对象来管理内存,其实这些智能指针对象严格意义来讲也可以算是auto类型(仁者见仁),这里不在多说了

以上是对于之前auto用法和作用的一点总结,欢迎补充:

c11的auto加入了根据初始化的值的类型来推断变量类型的功能,什么意思呢?举个例子:
以前我们要保存10这个数值,我们必须声明一个int型的变量a:
int a = 10;
我们要保存一个2.1这样的数值,我们必须声明一个float或者double型的变量b:
double b = 2.1;
现在我们可以用auto来实现这样的功能
auto a = 10
auto a = 2.1
你不用显示的指定a的类型,编译器会自动根据你初始化的数值来定义a的类型。
有人会觉得这样的功能很鸡肋呀,我既然要用10,我肯定知道我要使用的是一个整数类型呀,不需要编译器去推断呀?的确,但是某些时候,你可能不知道用户输入数值的类型,尤其是在泛型编程中,就体现出了auto的便捷了,我们再来看个例子:

点击(此处)折叠或打开

  1. template<class T> void printall(const vector<T>& v)
  2.     {
  3.         for (typename vector<T>::const_iterator p = v.begin(); p!=v.end(); ++p)
  4.             cout << *p << "\n";
  5.     }
我们在c11之前要在一个模板函数里面,遍历用户传来的容器中的元素,我们必须这样声明一个迭代器:
typename vector<T>::const_iterator p = v.begin()
因为编译器,不能推断用户输入的类型,但是现在有了auto这个东西,一切就变得很简单了:

点击(此处)折叠或打开

  1. template<class T> void printall(const vector<T>& v)
  2.     {
  3.         for (auto p = v.begin(); p!=v.end(); ++p)
  4.             cout << *p << "\n";
  5.     }
我们只需要将这个迭代器变量声明成一个auto类型,剩下的工作就交给编译器去做好了,是不是有种“清新爽洁不紧绷”的感觉!
不仅仅能够做这些,还有好戏在后头,因为它还能进行更强大的推理:

点击(此处)折叠或打开

  1. template<class T, class U> void multiply(const vector<T>& vt, const vector<U>& vu)
  2.     {
  3.         // ...
  4.         auto tmp = vt[i]*vu[i];
  5.         // ...
  6.     }
没有auto的时候我们真的很难处理这样的问题,例如:
multiply(double, int)
multiply(int, double)
为了处理上述的两种情况(要尽可能的保证结果的精度)我们很可能需要两个函数来处理,现在有了auto,用一个模板就能轻松搞定上述的问题:因为你不用操心我应该如何定义vt[i]*vu[i]返回值类型的问题了,是不是很cool!

不知道大家对于遍历数组的操作是不是感到很繁琐,对于这个问题我们在c11可以这样轻松的实现:

点击(此处)折叠或打开

  1. int a[10] = {1,2,3,4,5,6,7,8,9,0};
  2. for(auto x : a)
  3. {
  4.     cout << x << " ";
  5. }
  6. cout << endl;

我们还能这样操作一个容器:

点击(此处)折叠或打开

  1. void f(vector<double>& v)
  2. {
  3.     for (auto x : v) cout << x << '\n';
  4.     for (auto& x : v) ++x;    // using a reference to allow us to change the value
  5. }

我们甚至还可以这样来玩:

点击(此处)折叠或打开

  1. for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '\n';

总之,自从有了auto腰不酸了,腿不疼了,连碼代码都更有劲了!







阅读(10219) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~