做为一种计算机语言,C++经历了许多发展变化。程序员
固然,这些改变并非一蹴而就的。C++曾经缺少活力与创新,所以很不受欢迎。编程
可是在C++标准委员会决定加速发展这个语言以后,形势发生了改变。小程序
2011年起,C++一跃成为了具备活力、不断演进、广受喜好的计算机语言。
最后,若是你们若是在自学遇到困难,想找一个C++的学习环境,能够加入咱们的C++学习圈,点击我加入吧,会节约不少时间,减小不少在学习中遇到的难题。安全
C++蜕变后也并无简单多少,还是最难的编程语言之一。可是,C++确实比以前更加人性化了。数据结构
本文要讲的是的C++的一些新特性(以有8年历史的C++11为例),相信每一个程序员都会对这个话题感兴趣。编程语言
注:本文略过了一些高级特性。ide
当C++11第一次引入auto时,程序员们纷纷喜极而泣!函数
auto的意义是使C++编译器能够在编译时推导数据类型,这样就不用每次都要声明数据类型了。当数据类型为map<string,vector<pair<int,int>>>时尤其便捷。学习
不知道C++这七大特性,绝对枉为圈中人this
没有initializer,就没法声明数据类型(见第五行)。这是说得通的。第五行指令并无让编译器推导数据类型。
起初,auto的功能比较有限。在以后新版本的C++中,auto的功能愈来愈强大。
不知道C++这七大特性,绝对枉为圈中人
第七行和第八行中使用了括号初始化 (bracketedinitialization),这也是C++11的新特性之一。
请注意使用auto时,编译器必须可以推导数据类型。
一个有趣的问题是:若是写下autoa = {1, 2, 3}会发生什么?这是个编译错误吗?是一个矢量吗?
不知道C++这七大特性,绝对枉为圈中人
实际上,C++11引入了std::initializer_list<type>.若是声明auto,花括号初始化列表会被当作轻量级容器。
最终,正如前文所言,当数据结构复杂时,编译器类型推导颇有帮助:
不知道C++这七大特性,绝对枉为圈中人
别忘了检查第25行!auto [v1,v2] = itr.second纯粹是C++17的新特性。这个特性叫作结构化绑定。在旧版本C++中,程序员须要单独获取每一个变量。可是结构化绑定给这一过程带来了便利。此外,若是想得到数据使用引用(reference),只须要加上一个symbol--auto&[v1,v2] = itr.second.
C++11引入了lambda表达式,这相似于JavaScript里的匿名函数。它们都是函数对象,没有名字,且基于简洁的语法在不一样做用域上捕获变量。它们也能够被分配给变量。
若是须要在代码中进行一些小而快的操做,又不肯意为此单独写一个函数,那么Lambdas颇有用。另外一种常见用法是将lambdas做为比较函数。
不知道C++这七大特性,绝对枉为圈中人
以上例子能够说明不少问题。
首先,请注意花括号初始化是如何提高权重的。而后是通用的begin(),end() (这也是C++11的新增部分)。接着是做为数据比较器的lambda函数。lambda函数的参数被声明为auto(这是C++14的新增部分)。在C++14以前是不能对于函数参数使用auto 的。
正如现代C++的awesome库中定义的那样:
· []—不捕获任何对象。因此不能在lambda表达式内使用全局做用域的局部变量,只能使用参数。
· [=]— 按值捕获做用域中的局部对象(局部变量,参数)。只可以使用不可修改。
· [&]—按引用捕获做用域中的局部对象(局部变量,参数)。能够被修改。例子以下。
· [this]—按值捕获this 指针。
· [a, &b]—按值捕获对象a ,按引用捕获对象b。
因此,若是想在lambda函数内部将数据转换为其余格式,能够利用做用域的优点来运用lambda.好比:
不知道C++这七大特性,绝对枉为圈中人
在上面这个例子中,若是在lambda表达式中按值捕获([factor])局部变量,则不能改变第五行的factor.缘由很简单——没有权限。
最终,请注意示例中使用了val 做为引用 (reference). 这确保了lambda函数内部的任何变化都会改变vector.
不知道C++这七大特性,绝对枉为圈中人
学完现代C++后,她们乐开了花!(摄影:Ian Schneider 图源:Unsplash)
C++17的这个特性十分讨喜:
不知道C++这七大特性,绝对枉为圈中人
很明显,如今能够同时在if/switch句块内进行变量初始化和条件检查。这有助于保持代码简洁精炼。通用形式为:
if( init-statement(x);condition(x)) {
// do some stuff here
} else {
// else has the scope of x
// do some other stuff
}
constexpr 很棒!假如要评估一些表达式,且它的值一旦初始化就不会改变,那么能够预运算其值并将之做为宏。或者利用C++11提供的constexpr.
程序员倾向于尽可能减小程序运行时间。因此,若是能让编译器进行一些操做并减少程序运行的压力,那么就能够缩短运行时间。
不知道C++这七大特性,绝对枉为圈中人
以上代码是constexpr的常见例子之一。既然声明斐波那契数列函数为constexpr, 那么编译器就能够在编译时预运算fib(20). 因此编译以后,能够用constlong long bigval = 2432902008176640000来替代const longlong bigval = fib(20).
请注意,传递参数是一个const 值。这是被声明为constexpr的函数的一个重点——传递参数应该是constexpr或const。不然这里的函数会和普通函数同样,也就是说编译时不进行预运算。
变量也能够是constexpr. 在这种状况下,这些变量在编译时必须可评估;不然会出现编译错误。
有趣的是,后来在C++17中引入了constexpr-if 和constexpr-lambda.
与pair很是相似, tuple是各类数据类型的固定大小值的集合。
不知道C++这七大特性,绝对枉为圈中人
有时,相比于tuple,使用 std::array更方便。array相似于带有C++标准库的功能的plain C阵列。这个数据结构是C++11新增的。
这个特性的名字还挺啰嗦。从C++17开始,标准类模板也能够进行模板参数推导。以前,模板参数推导只支持函数模板。结果就是:
std::pair<std::string,int> user = {"M", 25}; // previous
std::pair user = {"M", 25}; // C++17
这种推导是“隐性的”。这对于tuple来讲就更方便了。
// previous
std::tuple<std::string, std::string, int> user ("M","Chy", 25);
// deduction in action!
std::tuple user2("M", "Chy", 25);
以上这一特性对不熟悉C++模板的人来讲没有太大用处。
指针有时很恐怖。因为C++语言为程序员提供了很大程度的自由,因此有时很容易搬起石头砸本身的脚。并且不少状况下,麻烦是由指针形成的。
幸运的是,C++11引入了智能指针,智能指针比普通指针便捷得多。它们经过适时释放内存来帮助程序员防止内存泄漏。它们还有助于代码达到异常安全等级。
C++为最新版本的计算机语言引入了许多全新的特性。若是你感兴趣,能够进行深刻了解。
不知道C++这七大特性,绝对枉为圈中人