c++11 特性(一)

初始化

C++ 11扩展了大括号{}的适用范围,既可以用于基本类型,也可以用于自定义类型:

int x = {5};

double y{3.5};

short quar[5]{1, 2, 3, 4, 5};

int* p = new int[5]{1, 2, 3, 4, 5};

创建对象时,也可以使用大括号链表来调用构造函数:

class Stump
{
Public:
    Stump(int r, double w) : roots(r), weight(w){}
Private:
    int roots;
    double weight;
};

Stump s1(3, 4.5); // old style
Stump s2{3, 4.5}; // new style
Stump s3 = {3, 4.5};     // new style

注意:使用初始化列表可以防止向下转型,如:

char c1 = 1.57e27;   // double-to-char, undefined behavior
char c1{1.57e27}; // double-to-char, compile error

std::initializer_list可以作为函数参数,如果一个类中的构造函数使用了这种方法,则其他函数将不能再使用其作为参数,这是为了防止调用二义性。
Initializer_list模板类提供了两个成员函数begin()和end(),用来指定列表的范围,如:

double sum(std::initializer_list<double> il)
{
    double total = 0;

    for(auto p = il.begin(); p != il.end(); p++)
       total += *p;
    return total;
}

double total = sum({1, 2.5, 8.3, 2.2, 1.0});

声明

C++提供了多种简化声明的方式,尤其在使用模板时更加方便。

1 auto

用来实现自动类型推断,如:

auto i = 112;     // i is type int

auto pt = &i;     // pt is type int*

double fm(double, int);

auto pf = fm;     // pf if type double(*)(double, int);

用于模板时形式简洁,如:

for(std::initializer_list<double>::iterator p = il.begin(); p != il.end(); p++)

改写为:

for(auto p = il.begin(); p != il.end(); p++)

2 decltype

将变量的类型指定为表达式的类型。

decltyte (x) y; 将y设为与x相同的类型,其中x是一个表达式。

3 返回类型后置

在函数名和参数列表后面指定返回类型。

double f1(double int);        // return double type

auto f2(double, int) -> double;   // new syntax, return double type

如果结合上模板表示返回类型,那就更好了,如下:

template<typename T, typename U>

auto eff(T t, U u) -> decltype(T * U)

{

}

4 模板别名

using =

C++中创建别名一般用typedef,如:

typedef std::vector<std::string>::iterator itType;

还可以这样做:

using itType = std::vector<std::string>::iterator;

5 nullptr

空指针

之前,C++使用0表示空指针,同样的0既可以表示整型,又可以表示空指针,比较混乱;新增的nullptr是指针类型,不能转换为整型。为了兼容性,C++目前仍然允许0表示空指针,即nullptr == 0的结果为true。

二者的差别在于,using可以使模板具体化,如:

using arr = std::array<T, 12>;//此时typedef不行。

4 智能指针

C++ 11摒弃了auto_ptr,新增了三种:unique_ptr、shared_ptr、weak_ptr。

5 异常

之前C++的语法中可以指出函数可能引发哪些异常,如:

void f1(int) throw(bad_alloc);  // 可能抛出bad_alloc异常

void f2(long long) throw();     // 不抛异常

C++摒弃了异常规范,新增了如下

Void f3(short, short) noexcept; // 不抛异常

6 作用域内枚举

传统的C++枚举的作用域在所属的域内,就是说同一作用域内不能出现两个同名的枚举变量。

C++ 11新增了一种枚举,使用class或者struct定义:

enum Old{yes, no};   // old style

enum class New{yes, no}; // new style

enum struct New{yes, no};   // new style

由于允许同名存在,因此引用时需要使用枚举名限定:New::yes。

7 对类的修改

在扩展类的设计方面,C++ 11很多改进,比如允许构造函数被继承、彼此调用、移动构造函数、移动赋值运算符等。

7.1 显示转换运算符

早期的C++会导致自动类型转换,比如:

class Plebe
{
    Plebe(int);
    explicit Plebe(double);
    ...
};

Plebe a, b;
a = 5;        //发生隐式类型转换,实则调用Plebe(5);
b = 0.5;      //不允许
b = Plebe(0.5);   //允许

C++ 11扩展了explicit,使得可以如下这样做:主要是针对转换函数:

比如:

operator int() const;
explicit operator double() const;

int n = a;    // allow

double x = b;     // not allow

x = double(b);    // allow

7.2 类内成员初始化

class Session
{
    int mem = 10;
    double mem2{2.35};
    ...

};

每天进步一点点,就是——拥有水滴石穿的坚持;懂得聚沙成塔的积累;磨练坚韧不拔的意志;学习脚踏实地的奋斗;提升立世做人的技巧;突破自我设限的障碍。
—戴明博士

猜你喜欢

转载自blog.csdn.net/programer_vc/article/details/78629858