现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

C++Primer第五版中的c++11特性归纳(三)

2019-04-28 06:20 工业·编程 ⁄ 共 2816字 ⁄ 字号 暂无评论

二十一、使用decltype简化返回类型定义

如果我们知道函数返回的指针指向哪个数组,就可以使用decltype关键字声明返回类型。例如,下面的函数返回一个指针,该指针根据参数i的不同指向两个已知数组中的某一个

int odd[] = {1,3,5,7,9};

int even[] = {0,2,4,6,8};

//返回一个指针,该指针指向含有5个整数的数组

decltype(odd) *arrPtr(int i){

return (i % 2) ? &odd : &even; // 返回一个指向数组的指针

}

arrPtr使用关键字decltype表示它的返回类型是一个指针,并且该指针所指的对象与odd类型一致。因为odd是数组,所以arrPtr返回一个指向含有5个整数的数组指针。

二十二、constexpr函数

constexpr函数是指能用于常量表达式的函数

定义constexpr函数的方法与其他函数类似,不过要遵循几项约定:函数的返回类型和所有形参的类型都是字面值类型,而且函数体中必须只有一条return语句。

constexpr int new_sz() {return 42};

constexpr int foo = new_sz(); //正确,foo是一个常量表达式

我们把new_sz定义成无参数的constexpr函数。因为编译器能在程序编译时验证new_sz函数返回的是常量表达式,所以可以用new_sz函数初始化constexpr类型变量foo。

二十三、使用=default生成默认构造函数

在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后面写上 = default来要求编译器生成构造函数。其中,=default既可以和声明一起出现在类的内部,也可以作为定义出现在类的外部。和其他函数一样,如果=default在类的内部,则默认构造函数是内联的

二十四、类对象成员的类内初始化

class Window_mgr{

private:

//这个Windoes_mgr追踪的screen

//默认情况下,一个这个Windoes_mgr包含一个标准尺寸的空白Screen

std::vector<Screen> screens(Screen(24, 80, ' ')};

};

当我们初始化类类型的成员时,需要为构造函数传递一个复合成员类型的实参。在此例中,我们使用一个单独的元素对vector成员执行了列表的初始化,这个screen的值被传递给vector<Screen>的构造函数,从而创建了一个单元素的vector对象。具体的说,Screen的构造函数接受了两个尺寸参数和一个字符值,创建了一个给定大小的空白对象。

二十五、委托构造函数

C++11新标准扩展了构造函数初始值的功能,使得我们可以定义所谓的委托构造函数。一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程,或者说它把它自己的一些(或者全部)指责委托给了其他构造函数。

和其他构造函数一样,一个委托构造函数也有一个成员初始值的列表和一个函数体。在委托构造函数内,成员初始值列表只有一个唯一的入口,就是类名本身。

class Sales_data{

public:

//非委托构造函数使用对应的实参初始化成员

Sales_data(std::string s, unsigned cnt, double price):

booksNo(s), units_sold(cnt), revenue(cnt*price){}

//其余构造函数全部委托给另一个构造函数

Sales_data():Sales_data("", 0, 0){}

Sales_data(std::string s):Sales_data(s, 0, 0){}

Sales_data(std::istream &is):Sales_data(){read(is, *this}

}

二十六、constexpr构造函数

constexpr构造函数可以声明为=default的形式,否则,constexpr构造函数就必须符合构造函数的需求(意味着不能包含返回语句),又符合constexpr函数的要求(意味着它能拥有的唯一可执行语句就是返回语句 )。

总和这两点可知,constexpr构造函数体一般来说应该是空的,通过前置关键字constexpr就可以声明一个constexpr构造函数:

class Debug{

public:

constexpr Debug(bool b = true): hw(b), io(b), other(b){}

}

constexpr构造函数必须初始化所有的数据成员,初始值或者使用constexpr构造函数,或者是一条常量表达式。

二十七、使用string对象处理文件名

在新C++标准中,文件名既可以是库类型string对象,也可以是C风格字符数组。旧版本的标准库只允许C风格字符数组

二十八、array和forward_list容器

forward_list和array是新C++标准增加的类型。与内置数组相比,array是一种更安全,更容易使用的数组类型

与内置数组相似,array对象的大小是固定的。因此,array不支持添加及删除元素以及改变容器大小的操作。

forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。

二十九、容器的cbegin和cend函数

以c开头的版本是新C++标准引入的,用以支持auto与begin和end函数结合使用。过去,没有其他选择,只能显式声明希望使用哪种类型的迭代器:

//显示指定类型

list<string>::iterator it5 = a.begin();

list<string>::const_iterator it6 = a.begin();

//是iterator还是const_iterator依赖于a的类型

auto it7 = a.begin(); //仅当a是const时,it7是const_iterator

auto it8 = a.cbegin(); //it8是const_iterator

当auto与begin或end结合使用时,获得的迭代器类型依赖于容器的类型,与我们想要如何使用迭代器毫不相关。但以c开头的版本还是可以获得const_iterator的,而不管容器类型是什么

三十、容器的列表初始化

在新标准中,我们可以对一个容器进行列表初始化:

//每个容器有三个元素,用给定的初始化器进行初始化

list<string> authors = {"Milton", "Shakespear", "Austen"};

vector<const char*> articles = {"a", "an", "the"};

这样做,我们就显式地指定了容器中每个元素的值。对于除array之外的容器类型,初始化列表还隐含地指定了容器的大小:容器将包含与初始值一样多的元素。

给我留言

留言无头像?