C++11 新特性<一>
来源:互联网 发布:如何设置淘宝客优惠券 编辑:程序博客网 时间:2024/04/30 09:05
18.1.1 新类型
C++11 新增了类型 long long 和 unsigned long long 以支持 64位(或更宽)的整型;
新增了类型 char16_t 和 char32_t ,以支持 16位 和 32位的字符表示; 还增加了 “原始” 字符串。
18.1.2 统一的初始化
C++11 扩大了用大括号括起来的列表(初始化列表)的适用范围,使其可用于所有内置类型和用户定义的类型(即类对象)。
适用初始化列表时,可添加等号(=),也可不添加。
int x = {5};double y {3.14};short quar[5] {1, 2, 3, 4, 5};int * arr = new int[4] {2, 4, 6, 8}; //创建对象时class Stump{private: int roots; double weight;public: Stump(int r, double w) : roots(r), weight(w) {}}; Stump s1(1, 11.1); //old styleStump s2{2, 22.2}; //C++11Stump s3 = {3, 33.3}; //C++11
1.缩窄(防止缩窄)
初始化列表语法可防止缩窄,即禁止将数值赋给无法存储它的数值变量。
char c1 = 1.55e27; // double-to-char, undefined behaviorchar c2 = 45968241; // int-to-char, undefined behavior //禁止缩窄的类型转换char c3 {1.55e27}; //double-to-char, compile-time errorchar c4 = {45968241}; //int-to-char, out of range, compile-time error //允许转换为更宽的类型char c5 {66}; //int-to-char, in range, alloweddouble c6 = {66}; //int-to-double, allowed
2.std::initializer_list
C++11 提供了模板类 std::initializer_list, 可将其用作构造函数的参数。
然而,如果类有将模板 std::initializer_list 作为参数的构造函数,则只有构造函数可以使用列表初始化形式。
列表中的元素必须是同一种类型或可以转换为同一种类型。
// STL 容器提供了将 std::initializer_list 作为参数的构造函数 vector<int> a1(10); // uninitialized vector with 10 elements vector<int> a2{10}; // initializer-list, a2 has 1 element set to 10 vector<int> a3{1, 2, 3}; // 3 elements set to 1, 2, 3 /* * 头文件 initializer_list 提供了对模板类 initializer_list 的支持。这个类包含成员函数 begin() 和 end(), * 可用于获取列表的范围。除用于构造函数外,还可将 initializer_list 用作常规函数的参数: */#include <initializer_list> double sum(std::initializer_list<double> i1); int main() { double total = sum( {2.5, 3.1, 4} ); // 4 converted to 4.0 …… } double sum(std::initializer_list<double> i1) { double tot = 0; for (auto p = il.begin(); p != il.end() ; p++) tot += p; return tot; }
18.1.3 声明
1> auto (自动类型推断)
auto maton = 112;// maton is type intauto pt = &maton;// pt is type int *double fm(double, int);auto pf = fm;// pf is type double (*) (double, int)// auto 简化模板声明for (std::initializer_list<double>::iterator p = il.begin(); p != il.end(); p++)//可替换为:for (auto p = il.begin(); p != il.end(); p++p)
2> decltype (将变量的类型声明为表达式指定的类型)
decltype(x) y;// 让 y 的类型与 x 相同, x 是一个表达式double x;int n;
decltype(x*n) q;// q same type as x*n, i.e., doubledecltype(&x) pd;// pd same as &x, i.e., double *//定义模板时特别有效,因为只有等到模板被实例化时才能确定类型template<typename T, typename U>void ef(T t, U u){decltype(T*U) tu;… …}// 其中 tu 将为表达式 T*U 的类型,这里假定定义了运算 T*U 。 例如,如果 T 为 char , U 为 short , 则 tu 将为 int 。// 指定的类型可以为 引用 和 constint j = 3;int &k = j;const int &n = j;decltype(n) i1;// i1 type const int &decltype(j) i2;// i2 type intdecltype((j)) i3;// i3 type int &decltype(k+1) i4;// i4 type int
3> 返回类型后置
C++11 新增了一种函数声明的语法:在函数名和参数列表后面(而不是前面)指定返回类型:
double f1(double, int);// traditional syntaxauto f2(double, int) -> double;// new syntax, return type is double//优点:可以使用 decltype 来指定模板函数的返回类型template<typename T, typename U>auto eff(T t, U u) -> decltype(T*U){. . .}// 这里解决的问题是:在编译器遇到 eff 的参数列表前, T 和 U 还不在作用于内,因此必须在参数列表后使用 decltype
4> 模板别名:using=
typedef std::vector<std::string>::iterator itType;//C++11 提供了另一种创建别名的方法using itType = std::vector<std::string>::iterator;// typedef 与 using 区别: using 可用于模板部分具体化, 而 typedef 不能template<typename T>using arr12 = std::array<T, 12>;// template for multiple aliases// 上述语句 具体化 目标板 array<T, int>(将参数 int 设置为 12)。std::array<double, 12> a1;std::array<std::string, 12> a2;//可将它们替换成:arr12<double> a1;arr12<std::string> a2;
5> nullptr
简言之:使数据各司其职 之前 0 可以表示 int , 同时 0 还可以表示 空指针, nullptr 专一的表示空指针 , 为了兼容 代表空指针的用法不变 。
所以 表达式 nullptr == 0 为 true, int 传参时可以体现出来, 传0没问题 ,但是 传 nullptr 就错了 ,这反映了 使用 nullptr 而不是 0 提供了更高的类型安全。
18.1.4 智能指针
C++11 摒弃了 auto_ptr , 并新增了三种智能指针:unique_ptr , shared_ptr 和 weak_ptr。
18.1.5 异常规范方面的修改
之前
void f501(int) throw(bad_dog); // can throw type bad_dog excetpion
void f733(long long) throw(); // doesn't throw an exception
与 auto_ptr 一样,C++ 编程社区的集体经验表明,异常规范的效果没有预期的好。因此,C++ 摒弃了异常规范。然而,标准委员会认为,
指出函数不会引发异常有一定的价值,他们为此添加了关键字 noexcept:
void f875(short, short) noexcept; //doesn't throw an exception
18.1.6 作用域内枚举
//由 class 或者 struct 定义。 解决了同一个作用域内 枚举成员同名的问题, 移植性问题 以及 类型检查低级问题enum Old1 {yes, no, maybe};// traditional formenum class New1 {never, sometimes, often, always};// new formenum struct New2 {never, lever, sever};// new form//新枚举要求进行显示限定,以免发生名称冲突。因此,引用特性枚举时,需要使用 New1::never 和 New2::never 等
18.1.7 对类的修改
1> 显示转换运算符
// C++ 引入了关键字 explicit , 以禁止单参构造函数导致的自动和转换class Plebe{Plebe(int);// automatic int-to-plebe conversionexplicit Plebe(double);//requires explicit use...};...Plebe a, b;a = 5;// implicit conversion, call Plebe(5)b = 0.5;// not allowedb = Plebe(0.5);// explicit conversion// C++11 拓展了 ecplicit 的这种用法,使得可对转换函数做类似的处理class Plebe{// conversion functionsoperator int() const;explicit operator double() const;
...};...Plebe a, b;int n = a;// int-to-plebe automatic conversiondouble x = b;// not allowedx = double(b);// explicit conversion, allowed
2>类内成员初始化
class Session{int mem1 = 10;double mem2 {1966.54};short mem3;public:Session(){}Session(short s) : mem3(s) {}Session(int n, double d, short s) : mem1(n), mem2(d), mem3(s) {}};// 注:可使用 等号 或者 大括号 版本的初始化,但不能使用 圆括号 版本的初始化。// 构造函数 初始化列表提供的值 会将默认值 覆盖 (即:覆盖类内成员初始化)
1> 基于范围的 for 循环
double prices[5] = {4.1, 5.2, 6.3, 7.4, 8.5};for (double x : prices) // 当然,这里的 double 可以用 auto 来替代 std::cout<<x<<std::endl; std::vector<int> vi(6);for (auto &x : vi) x = std::rand(); // 循环中修改元素内容 可使用引用类型
2> 新的 STL 容器
新增 forward_list(单项链表) , unordered_map , unordered_multimap , unordered_set , unordered_multiset
还增加了模板数组 array std::array<int, 360> arr; //arr of 360 ints
3> 新的 STL 方法
cbegin() 和 cend(); 简言之,元素具有 const 属性
4> valarray 升级
5> 摒弃 export
6> 尖括号
std::vector<std::list<int> > v1; // 避免 >> 与 > > 混淆
std::vector<std::list<int>> v1; // ok in C++11
18.1.9 右值引用
C++11新增了右值引用,使用 && 表示。
右值引用可关联到右值,即可出现在赋值表达式的右边,但不能对其应用地址运算符的值。右值包括字面常量(C-风格字符串除外,他表示地址)、诸如 x+y 等表达式以及返回值的函数(条件是该函数返回的不是引用):
int x = 10;int y = 23;int && r1 = 13;int && r2 = x + y;double && r3 = std::sqrt(2.0);注意:r2 关联到的是 x+y 得到的结果(即 33),即使 修改了 x 或者 y 的值,也不会影响到 r2。
有趣的是,将右值关联到右值引用导致该右值被存储到特定的位置,且可以获取该位置的地址。也就是说,虽然不能将运算符 & 用于 13, 但可将其用于 r1。 通过将数据与特定的地址关联,使得可以通过右值引用来访问该数据。参考如下代码:
double func(double tf) { return 5.0*(tf-32.0)/9.0; }
以下代码是在 XCode 下 init 函数 中写的代码 你完全可以 在 int main(){} 中写(如果 windows 下 支持的话)
double tc = 21.5;double && rd1 = 7.07;double && rd2 = 1.8 * tc + 32.0;double && rd3 = func(rd2);std::cout<<" tc value and address: "<<tc<<", "<<&tc<<std::endl;std::cout<<"rd1 value and address: "<<rd1<<", "<<&rd1<<std::endl;std::cout<<"rd2 value and address: "<<rd2<<", "<<&rd2<<std::endl;std::cout<<"rd3 value and address: "<<rd3<<", "<<&rd3<<std::endl;运行结果:
- C+11 新特性
- C#: VS2008的新特性(一)
- C++11 新特性<一>
- [C++]C++11新特性
- 【C++】 C++11新特性
- oracle10g/11g 新特性一(ASM)
- C++11新特性(一)
- jdk7新特性一
- CSS3新特性(一)
- css3新特性一
- Oracle 12c 新特性之 Multitenant Architecture (一)
- Oracle 数据库12c新特性总结(一)
- Oracle 数据库12c新特性总结(一)
- SuperMap iServer 8C(2017),一大波新特性来袭
- 【C++】了解C++11新特性
- C++:C++11新特性详解(1)
- 12c新特性
- Objective-C新特性
- android中修改framework层代码后怎样操作才能看到修改后的效果?
- Spark 学习总结(学习资料一)
- 调用库函数之后检查errno《C专家编程》
- 怎么在数据库表里面自动插入日期字段
- 原创文章3
- C++11 新特性<一>
- python打印列表中的内容,而不是unicode字符
- 枚举类型
- Tomcat7新特性?cookie HttpOnly的那些事(sessionid获取麻烦了)
- 创建一个有序链表
- 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。
- 公务车订购国产化 多款车型入采购名单
- POJ 1948 Triangular Pastures (用所有的线段组成最大的三角形) DP || 携程员工运动会场地问题
- 十种常用排序算法浅析 附C++实现