没有合适的资源?快使用搜索试试~ 我知道了~
本文讨论了10个C++11中新增的特性,所有的C++开发者都应学习和使用。C++11无论是语言本身还是标准库都新增了许多新的东西,而本文仅仅是介绍了皮毛。但我认为其中的部分新特性应该被应用到开发者的日常开发中。已有许多文章介绍了C++11与之前版本的不同之处,下面我将尝试列出当前应作为准则的那些C++的特性。 内容索引: 自动类型(auto) 空指针(nullptr) 集合循环(Range-based for loops) override和final标识(override and final) 强类型的枚举类型(Strongly-typed enums)
资源推荐
资源详情
资源评论
C++工程师需要掌握的工程师需要掌握的10个个C++11特性特性
本文讨论了10个C++11中新增的特性,所有的C++开发者都应学习和使用。C++11无论是语言本身还是标准库都新增了许
多新的东西,而本文仅仅是介绍了皮毛。但我认为其中的部分新特性应该被应用到开发者的日常开发中。已有许多文章介绍了
C++11与之前版本的不同之处,下面我将尝试列出当前应作为准则的那些C++的特性。
内容索引:
自动类型(auto)
空指针(nullptr)
集合循环(Range-based for loops)
override和final标识(override and final)
强类型的枚举类型(Strongly-typed enums)
智能指针(Smart pointers)
Lambdas表达式(Lambdas)
非成员的begin()和end()函数(non-member begin() and end())
静态断言和类型特性(static_assert and type traits)
移动语义(Move semantics)
自动类型
在C++11之前auto关键字用于标识自动存储的临时变量,而在新标准中auto用于类型推断。auto现在是一种类型占位符,
告诉编译器需要从变量的初始定义中推断出该变量的实际类型。它可用于不同域中变量的定义,如命名空间、块、for循环中
的初始化语句等。
1 auto i = 42; // i is an int
2 auto l = 42LL; // l is an long long
3 auto p = new foo(); // p is a foo*
Using auto usually means less code (unless your type is int which is one letter shorter). Think of iterators in STL that
you always had to write while iterating over containers. It makes obsolete creating typedefs just for the sake of simplicity.
使用auto可以减少代码长度(int除外,它比auto还少一个字符),想一想STL中每次需要遍历容器时你不得不写一遍的迭
代器知道auto有多好用了。它使得创建typedef来精简代码成为了过时的技术。
1 std::map<std::string, std::vector<int>> map;
2 for(auto it = begin(map); it != end(map); ++it)
3 {
4 }
或许你已注意到了auto不能作为函数的返回类型。但是在函数尾标注了函数的返回类型时,可以在写函数返回值类型的地
方使用auto(但这样用没什么意义,应该是作为到C++14的过渡吧)。这种情况下auto并没有让编译器去推断返回类型,而只
是告诉它到函数尾去查看返回类型。在下面的例子中,函数compose的返回类型是表达式(t1+t2)的返回类型。
1 template <typename T1, typename T2>
2 auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
3 {
4 return t1+t2;
5 }
6 auto v = compose(2, 3.14); // v's type is double
空指针
C98中空指针的值为0,由于隐式转换为整型带来了很多弊端。而关键字nullptr提供了一个std::nullptr_tr类型的值专门来表
示空指针的含义。隐式转换可以发生在从nullptr到任何指针类型的空指针值或任何成员指针类型的空指针值,也可以转换为
bool类型(作为false),但不会发生隐式转换为整型的情况。
1 void foo(int* p) {}
2
3 void bar(std::shared_ptr<int> p) {}
4
5 int* p1 = NULL;
6 int* p2 = nullptr;
7 if(p1 == p2)
8 {
9 }
10
11 foo(nullptr);
12 bar(nullptr);
13
14 bool f = nullptr;
15 int i = nullptr; // error: A native nullptr can only converted to bool or, using reinterpret_cast, to an integral type
为了向后兼容,0仍然可以作为空指针的值。
集合循环
C++11扩展了for表达式以支持遍历集合时类似“foreach”样式的功能。新的形式可以遍历C风格的数组、初始化列表以及任
何重载了非成员函数begin()和end()的数据集合。
This for each for is useful when you just want to get and do something with the elements of a collection/array and don't
care about indexes, iterators or number of elements.
如果你仅仅是想对集合中的元素做点什么,而并不关心集合中的索引、迭代器、元素个数等,那么逐个访问的for语句是
个不错的选择。
1 std::map<std::string, std::vector<int> > map;
2 std::vector<int> v;
3 v.push_back(1);
4 v.push_back(2);
5 v.push_back(3);
6 map["one"] = v;
7
8 for(const auto& kvp : map)
9 {
10 std::cout << kvp.first << std::endl;
11
12 for(auto v : kvp.second)
13 {
14 std::cout << v << std::endl;
15 }
16
17 }
18
19 int arr[] = {1,2,3,4,5};
20 for(int& e : arr)
21 {
22 e = e*e;
23 }
override和final标识
我一向认为C++中虚拟方法的设计很差,它没有(现在也没有)一个强制机制来标记虚拟方法在派生类中的重写情况。
virtual关键字是可选的,有时你必须沿着继承链找到顶端的父类来判断这个方法是否为虚拟方法,降低了代码可读性。因此我
提倡在派生类中使用virtual关键字以让代码更容易阅读。但还是可能出现一些微妙的错误,看看下面的例子:
1 class B
2 {
3 public:
4 virtual void f(short) {std::cout << "B::f" << std::endl;}
5 };
6
7 class D : public B
8 {
9 public:
10 virtual void f(int){std::cout << "D::f" << std::endl;}
11 };
D::f原本要重写B::f的,但由于参数的类型一个是short而另一个是int,造成函数签名不同,因此B::f只是一个拥有相同名字
(而且被重载了)的另一个方法,并没有被重写。你可能希望通过指向B的指针访问f()函数输出D::f,但它输出的却是B::f。
Here is another subtle error: the parameters are the same, but the method in the base class is marked const, while
method in the derived is not.
还有一个微妙的错误:函数参数相同,但基类中该方法被标记为const,而派生类中没有标记。
1 class B
2 {
3 public:
4 virtual void f(int) const {std::cout << "B::f" << std::endl;}
5 };
6
7 class D : public B
8 {
9 public:
10 virtual void f(int) {std::cout << "D::f" << std::endl;}
11 };
这两个方法仍然是重载的关系而不是重写。如果你通过指向B的指针访问f()输出的是B::f而不是D::f。
现在这个问题得到了解决。C++11新增了两个标记(注意不是关键字):override和final。override表明一个方法是对基
类中虚拟方法的重写,final表明派生类中的方法不能重写虚拟方法。第一个例子如下:
1 class B
2 {
3 public:
4 virtual void f(short) {std::cout << "B::f" << std::endl;}
5 };
6
7 class D : public B
8 {
9 public:
10 virtual void f(int) override {std::cout << "D::f" << std::endl;}
剩余8页未读,继续阅读
资源评论
weixin_38632797
- 粉丝: 6
- 资源: 946
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Redis和Elasticsearch的日志与指标处理系统.zip
- 学习记录111111111111111111111111
- (源码)基于Python和Selenium的jksb系统健康申报助手.zip
- (源码)基于HiEasyX库的学习工具系统.zip
- (源码)基于JSP+Servlet+JDBC的学生宿舍管理系统.zip
- (源码)基于Arduino和Raspberry Pi的自动化花园系统.zip
- (源码)基于JSP和Servlet的数据库管理系统.zip
- (源码)基于Python的文本相似度计算系统.zip
- (源码)基于Spring Boot和Redis的高并发秒杀系统.zip
- (源码)基于Java的Web汽车销售管理系统.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功