c++11 特性(二)
来源:互联网 发布:学软件开发学校 编辑:程序博客网 时间:2024/05/17 21:39
8 模板和STL方面
为了改善模板和标准化方面的易用性,C++ 11做了多个改进:
8.1 改进的for循环
double prices[5] = {1, 2, 3, 4, 5};for(double x : prices)for(auto x : prices)
如果要在循环中修改数组或容器中的每个元素,可以使用引用:
for(auto& x : prices)
8.2 新增的STL容器
C++ 11新增了forward_list、unordered_map、unordered_multimap、unordered_set、unordered_multiset。
新增了模板array,实例化时指定元素类型和个数:
std::array<int, 10> ar; // 10个int
8.3 新增STL方法
cbegin()、cend()、crbegin()、crend()。这几个方法将容器元素视为const。
8.4 valarray升级版
对于valarray模板,C++ 11新增了两个方法begin()和end()。
8.5 摒弃了export
C++ 98增加的关键字export可以让程序员将模板定义放在接口文件中,实现文件中放置方法体,但是实践证明这一点也不现实,因此C++ 11把它摒弃了。
8.6 尖括号
旧时的C++要求在定义嵌套的模板时,两个尖括号之间必须有空格,比如: vector<list<int> >
,但是C++ 11中不再需要这样了,比如vector<list<int>>
也可以通过的。
9 右值引用
C++新增了右值引用,使用&&表示。【相对于左值,右值表示字面常量、表达式、函数的非引用返回值等】
如:
int&& r1 = 12;
int x = 5;
int y = 8;
int&& r2 = x + y;
我们可以通过r1来修改12,很方便。
10 移动语义和右值引用
10.1 为何需要移动语义
移动语义就是为了避免多余的复制工作,就是说与其复制,还不如将源地址传给使用者,因为有时复制工作确是没什么用。
要实现移动语义,需要采用某种措施让编译器知道到底什么情况下需要复制,什么情况下不必复制。这时,右值引用就可以配上用场了。
传统的复制构造函数执行深复制,并且不改变实参,因此,参数为const类型;
移动构造函数只是更改了引用记录,并且可能会改变实参,因此,参数必须是非const类型;
如下实例:
class Use{public: Use(); Use(const Use& f); // copy constructor Use(Use&& f); // move constructor ...private:int n;char* pc;};...Use::Use(const Use& f) : n(f.n) // 深复制{ pc = new char[n]; for(int i = 0; i < n; i++) pc[i] = f.pc[i];}Use::Use(Use&& f) : n(f.n){ pc = f.pc; // 移动构造,转移控制权 f.pc = nullptr; f.n = 0;}
10.2 移动构造解析
虽然移动构造定义好了,但是如何调用呢,也就是说什么情况下才会发生移动构造呢?
必须使用右值引用调用:
Use two = one; // match Use::Use(const Use&);Use four(one + three); // match Use::Use(Use&&);
因为one是左值,而one + three是右值。
移动赋值情况类似,不记录了。
10.3 强制移动
移动构造和移动赋值使用右值引用,如果需要让他们操作左值呢?
答案是使用static_cast<>将对象强制转换为Use&&即可。不过在C++ 11种提供了更便捷的操作,在头文件utility中声明的函数std::move(…)。
如果使用了std::move()函数调用,但是类中却没有定义移动相关函数,那么编译器会调用传统版本的移动构造函数和移动赋值操作符。
11 新的类功能
假设你为类定义了构造函数,那么类就不会自动提供默认的构造函数了,然而,如果你仍然想使用类提供的默认版本,那么可以使用default关键字:
class Some{public: Some(Some&&); Some() = default; // use default constructor ...};
相反地,如果要禁用编译器提供的默认函数,可以使用delete:
class Some{public: Some(Some&&); Some() = default; // use default constructor Some(const Some&) = delete; //disable copy constructor ...};
当然要想禁用某个编译器提供的函数也可以显式声明为private,但是使用delete更方便且不易出错。
注意:default关键字只能用于6个特殊函数,而delete却能够用于任何成员函数。
委托构造
如果一个类包含多个构造函数,C++ 11允许在一个构造函数中的定义中使用另一个构造函数,但这必须通过初始化列表进行操作,如下:
class Notes{ int k; double x; string s;public: Notes(int kk, double xx, string ss) : k(kk), x(xx), s(ss){ } Notes(int kk) : Notes(0, 0.5, “benxin”){ k = kk; } ...};
继承构造
C++ 11允许派生类继承基类的构造函数。C++ 98提供了一种让某个名称空间中的同名重载函数都可用的语法,如下:
namespace Box{ int fn(){} int fn(int){} int fn(double){}}
using Box::fn;该语句使得fn的所有重载版本都可用。我们一般使用这种方法在派生类中调用基类的同名函数。之所以提供这种语法,就是因为覆盖是以函数名为基础的,不论参数是否对应都将被覆盖。
C++ 11将这种语法用于构造函数中,使得派生类将继承基类的构造函数(默认构造函数、复制构造函数、移动构造函数除外)。
- C# 特性学习(二)
- c++11 特性(二)
- C++Primer第五版中的c++11特性归纳(二)
- Oracle 数据库12c新特性总结(二)
- Objective-C的面向对象特性(二)
- 特性二、Objective-C的Attributed属性
- C语言的角落(二)——你不一定知道的C语言特性
- C+11 新特性
- 【C#】特性(Attribute)
- Java5新特性(二)
- Oracle Flashback特性(二)
- jdk新特性(二)
- OpenCV轮廓特性(二)
- JS高级特性(二)
- Swift3新增特性(二)
- Swift3废除特性(二)
- 浅谈 TypeScript 特性 (二)
- (二)python高级特性
- 2018年AI智商将达到多少?未来智能实验室启动第三次世界AI智商评测
- 中央、国务院:5G网络及业务全面支持IPv6(附解析)
- 用脑科学支持人工智能
- 简单讲解一下冒泡排序的原理 及代码
- 取消chrome浏览器下input和textarea的默认样式
- c++11 特性(二)
- bzoj4241 历史研究 (回滚莫队)
- 手游开发如何选择后端服务
- 无人驾驶汽车渐行渐近:百度宣布将于明年7月实现量产
- 机器学习期望最大算法:实例解析
- python中redis字符串操作
- 印度支持苹果扩大在印制造业务计划:谁的让步?
- cookie和session的区别
- 算法之路之征服上海交大的oj- 二哥的储蓄计划