优雅的C++11,现在说11年的事儿是不是有点落后了?
自动类型推导 auto
- auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以简化我们的编程工作;
- auto是在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响;
- auto也并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
auto对引用的推导默认为值类型,可以指定引用修饰符设置为引用。
对指针的推导默认为指针类型,当然,也可以指定*修饰符(效果一样)
推导常量
萃取类型 decltype
decltype实际上有点像auto的反函数,使用auto可以用来声明一个指定类型的变量,而decltype可以通过一个变量(或表达式)得到类型。
有没有联想到STL中的萃取器?写模版时有了这个是不是会方便很多。
返回类型后置语法
C++11支持返回值后置
例如:
auto用于占位符,真正的返回值在后面定义; 这样的语法用于在编译时返回类型还不确定的场合; 比如有模版的场合中,两个类型相加的最终类型只有运行时才能确定。
auto用于占位符,真正的返回值类型在程序运行中,函数返回时才确定;不用auto占位符,直接使用decltype推导类型。
decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs)
这样写,编译器无法通过,因为模版参数lhs和rhs在编译期间还未声明; 当然,这样写可以编译通过:decltype( (*(Lhs*)0) + (*(Rhs*)0) ) adding_func(const Lhs &lhs, const Rhs &rhs)
但这种形式实在是不直观,不如auto占位符方式直观易懂。
空指针标识 nullptr
空指针标识(nullptr)(其本质是一个内置的常量)是一个表示空指针的标识,它不是一个整数。这里应该与我们常用的NULL宏相区别,虽然它们都是用来表示空置针,但NULL只是一个定义为常整数0的宏,而nullptr是C++11的一个关键字,一个内建的标识符。 nullptr和任何指针类型以及类成员指针类型的空值之间可以发生隐式类型转换,同样也可以隐式转换为bool型(取值为false)。但是不存在到整形的隐式类型转换。 有了nullptr,可以解决原来C++中NULL的二义性问题;
区间迭代
C++11扩展了for的语法,终于支持区间迭代,可以便捷的迭代一个容器的内的元素;
如果有更为复杂的场景,使用auto的优势立刻体现出来:
lambda表达式的引入
不过现在好多了,lambda表达式允许用”inline”的方式来写函数了:sort(myvector.begin(), myvector.end(), [](int i, int j) { return i< j; });
真是亲切!lambda的引入应该会增加大家对STL算法的使用频率。(这里不过分介绍lambda,针对lambda用法发过类似文章)。
原生字符串
比如,你用标准regex库来写一个正则表达式,但正则表达式中的反斜杠’\’其实却是一个“转义(escape)”操作符(用于特殊字符),这相当令人讨厌。考虑如何去写“由反斜杠隔开的两个词语”这样一个模式(\w\\w):string s = "\\w\\\\\\w"; // 不直观、且容易出错
请注意,在正则表达式和普通C++字符串中,各自都需要使用连续两个反斜杠来表示反斜杠本身。然而,假如使用C++11的原生字符串,反斜杠本身仅需一个反斜杠就可以表示。因而,上述的例子简化为:string s = R"(\w\\\w)"; // ok
初始化列表及统一初始化方法
在过去对vector的多个初始化,我们需要这样:
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector
现在,我们可以这样:
std::vector
初始化表有时可以像参数那样方便的使用。看下边这个例子x,y,z是string变量,Nocase是一个大小写不敏感的比较函数):
auto x = max({x,y,z},Nocase());
初始化列表不再仅限于数组。对于常见的map、string等,我们可以使用以下语法来进行初始化
终章
閱讀更多 C語言源代碼計劃 的文章