文章目录
- enum枚举类型
- decltype
- 引用
- 宏
- 成员初始化列表
- initializer_list列表初始化
enum枚举类型
限定作用域的枚举类型
enum class open_modes{intput, output, append};
不限定作用域的枚举类型
enum color{red, yellow, green};
enum {floatPrec=6, doublePrec=10};
decltype
decltype关键字用于检查实体的声明类型或表达式的类型及值分类。语法:
decltype (expression)
decltype的使用
//尾置返回允许我们在参数列表之后声明返回类型
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
//处理序列
return *beg;//返回序列中一个元素的引用
}
//为了使用模板参数成员,必须用typename
template <typename It>
auto fcn2(It beg, It end) -> typename remove_reference<decltype(*beg)>::type
{
//处理序列
return *beg;//返回序列中一个元素的拷贝
}
引用
左值引用
常规引用,一般表示对象的身份。
右值引用
右值引用就是必须绑定到右值(一个临时对象、将要销毁的对象)的引用,一般表示对象的值。
右值引用可实现转移语义(Move Semantics)和精确传递(Perfect Forwarding),它的主要目的有两个方面:
消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
能够更简洁明确地定义泛型函数。
引用折叠X& &
、X& &&
、X&& &
可折叠成X&
X&& &&
可折叠成X&&
宏
宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。
成员初始化列表
好处
更高效:少了一次调用默认构造函数的过程。
有些场合必须要用初始化列表:
常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化。
initializer_list列表初始化
用花括号初始化器列表初始化一个对象,其中对应构造函数接受一个std::initializer_list
参数。
initializer_list使用
#include<iostream>
#include<vector>
#include<initializer_list>
template<class T>
struct S{
std::vector<T> v;
S(std::initializer_list<T> l) : v(l){
std::cout << "constructed with a " << l.size() << "-element list\n";
}
void append(std::initializer_list<T> l){
v.insert(v.end(), l.begin(), l.end());
}
std::pair<const T*, std::size_t> c_arr() const{
return {&v[0], v.size()}; //在return语句中复制列表初始化
//这不使用std::initializer_list
}
};
template <typename T>
void templated_fn(T) {}
int main()
{
S<int> s = {1, 2, 3, 4, 5}; //复制初始化
s.append({6, 7, 8}); //函数调用中的列表初始化
std::cout<<"The vector size if now " << s.c_arr().second << " ints:\n";
for(auto n : s.v)
std::cout << n << ' ';
std::cout << '\n';
std::cout << "Range-for over brace-init-list: \n";
for(int x : {-1, -2, -3})
std::cout << x << ' ';
std::cout<<'\n';
auto al = {10, 11, 12}; //auto的特殊规则
std::cout<<"The list bound to auto has size() = " <<al.size() << '\n';
// templated_fn({1, 2, 3}); //编译错误! "{1, 2, 3}"不是表达式,
//它无类型,故T无法推导
templated_fn<std::initializer_list<int>>({1, 2, 3}); //OK
templated_fn<std::vector<int>>({1, 2, 3}); //也OK
}