###if/switch变量声明强化 在传统 C++ 中,变量的声明虽然能够位于任何位置,甚至于 for 语句内能够声明一个临时变量 int,但始终没有办法在 if 和 switch 语句中声明一个临时的变量。 C++17 消除了这一限制,使得我们可以在 if(或 switch)中完成这一操作:
1 2 3 4 5
// 将临时变量放到 if 语句内 if (const std::vector<int>::iterator itr = std::find(vec.begin(), vec.end(), 3); itr != vec.end()) { *itr = 4; }
初始化列表
在传统 C++ 中,不同的对象有着不同的初始化方法,例如普通数组、 POD (Plain Old Data,即没有构造、析构和虚函数的类或结构体) 类型都可以使用 {} 进行初始化,也就是我们所说的初始化列表。 而对于类对象的初始化,要么需要通过拷贝构造、要么就需要使用 () 进行。 这些不同方法都针对各自对象,不能通用。
为解决这个问题,C++11 首先把初始化列表的概念绑定到类型上,称其为 std::initializer_list,允许构造函数或其他函数像参数一样使用初始化列表,这就为类对象的初始化与普通数组和 POD 的初始化方法提供了统一的桥梁,例如:
classMagicFoo { public: std::vector<int> vec; MagicFoo(std::initializer_list<int> list) { for (std::initializer_list<int>::iterator it = list.begin(); it != list.end(); ++it) vec.push_back(*it); } }; intmain(){ // after C++11 MagicFoo magicFoo = {1, 2, 3, 4, 5}; MagicFoo magicFoo {1, 2, 3, 4, 5};
std::cout << "magicFoo: "; for (std::vector<int>::iterator it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) std::cout << *it << std::endl; }
这种构造函数被叫做初始化列表构造函数,具有这种构造函数的类型将在初始化时被特殊关照。
初始化列表除了用在对象构造上,还能将其作为普通函数的形参,例如:
1 2 3 4 5 6 7
public: voidfoo(std::initializer_list<int> list){ for (std::initializer_list<int>::iterator it = list.begin(); it != list.end(); ++it) vec.push_back(*it); }
intmain(){ auto [x, y, z] = f(); std::cout << x << ", " << y << ", " << z << std::endl; return0; }
类型推导
C++11 引入了 auto 和 decltype 这两个关键字实现了类型推导,让编译器来操心变量的类型。这使得 C++ 也具有了和其他现代编程语言一样,某种意义上提供了无需操心变量类型的使用习惯。
auto
使用 auto 进行类型推导的一个最为常见而且显著的例子就是迭代器。你应该在前面的小节里看到了传统 C++ 中冗长的迭代写法:
1 2 3 4 5 6 7
// 在 C++11 之前 // 由于 cbegin() 将返回 vector<int>::const_iterator // 所以 it 也应该是 vector<int>::const_iterator 类型 for(vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it)
//C++11之后 for (auto it = list.begin(); it != list.end(); ++it)
注意:auto 还不能用于推导数组类型:
1 2 3 4
auto auto_arr2[10] = {arr}; // 错误, 无法推导数组元素类型
2.6.auto.cpp:30:19: error: 'auto_arr2' declared as array of 'auto' auto auto_arr2[10] = {arr};
decltype
decltype 关键字是为了解决 auto 关键字只能对变量进行类型推导的缺陷而出现的。它的用法和 typeof 很相似:decltype(表达式)
1 2 3 4 5 6 7 8 9
auto x = 1; auto y = 2; decltype(x+y) z; if (std::is_same<decltype(x), int>::value) std::cout << "type x == int" << std::endl; if (std::is_same<decltype(x), float>::value) std::cout << "type x == float" << std::endl; if (std::is_same<decltype(x), decltype(z)>::value) std::cout << "type z == type x" << std::endl;
其中,std::is_same<T, U> 用于判断 T 和 U 这两个类型是否相等。输出结果为:
1 2
type x == int type z == type x
尾返回类型推导
在传统 C++ 中我们必须这么写:
1 2 3 4
template<typename R, typename T, typename U> R add(T x, U y){ return x+y; }