后现代的系统编程语言-C++ | TW洞见

C++作为一门经典的编程语言,从上世纪八十年代起至今一直被广泛应用在系统开发和高性能计算领域。近几年来随着各种编程语言和范式的兴起,C++的身影渐渐淡出了人们的视野。但是作为一个仍在不断进步的语言,C++在最近几年飞速发展,已经具备了现代语言应有的特性,而且也有了许多已有的和正在进行的新的拓展。

经典的C++

作为C语言的超集,一方面,C++集成了C在系统编程优点,能够精确的控制内存中的每一个bit;另一方面,提供了丰富的抽象机制和编程范式,引入了面向对象、泛型编程和函数式编程等风格。因为这一点,C++拥有了与C媲美的运行时性能,另一方面,也简化了C语言带来的领域建模的难度。但是因为C++的整体设计结合了多种风格,几乎相当于嵌套了几个小语言的一个庞大的系统,这也使得C++的整体易学性和易用性上有些差劲。同时,由于标准库更新跟不上需求,在诸如Concurrency/Network等应用层的软件设计方面逐渐被Java等后来者取代。而且,各个C++厂商对编译器的实现并没有完全参考ISO标准,也造成了很多跨平台可移植性和兼容性问题。

现代C++

C++在最近几年进行了几次探索和蜕变,让整个语言变得更具备现代化的特色。

资源管理

RAII(Resource Aquiration is Initialization,资源获取即初始化)作为C++的特色之一,被广泛地应用到C++的程序中。RAII通过堆对象的生命周期来控制资源(包括堆内存、文件句柄、网络连接等)的生命周期,使得资源管理变得更加自动化,同时也避免了引入垃圾回收带来的运行时负担。但这种模式有一个很重要的问题,就是当需要对资源进行共享时,需要做更多额外的工作来进行检查和同步等工作。

作为更现代的资源管理方式,C++11中引入了两种智能指针,std::shared_ptr和std::unique_ptr。前者拥有线程安全的引用计数,后者则是通过所有权(owenrship)转移来控制资源的生存周期。C++11中也引入了右值引用和移动语义,来避免资源传递的过程中的不必要的复制。

与Rust中的生命周期(Lifetime)和所有权(Ownership)的概念类似,C++的std::unique_ptr在每一次值传递的时候将自身持有的资源转移到赋值的目标,同时结合移动语义,将赋值过程进一步地优化。

Lambda

Functor作为C++ STL的一个重要组件,也是C++中被使用很多的一个功能。一个Functor其实就是一个重载了operator()的类的实例对象,这种对象配合C++模版的行为,可以被简单看成一个函数来调用,所以被称为Functor(函子)。但是,由于C++对于匿名类和内部类支持并不够好,使用Functor必须提前进行设计。一方面不方便使用,另一方面,定义和使用分离,对代码的组织和理解也造成了一定的困难。

首先,lambda作为Functor的替代品,解决了不能即时定义并使用的问题。配合STL中的容器和算法,lambda也能将C++的函数式风格发挥到极致。其次,出于C++一贯对性能和抽象的考虑,引入了lambda capture的概念,使得对象的生命周期能够绑定到lambda表达式,也就能够构建出闭包对象(closure)。另外,C++14中加入的generic lambda,增强了lambda的类型推导算法,在不损失类型安全特性的基础上,让组合式编程(Combinator-based Programming)更加易于实现。

并发

在C++设计的初期,并发并未作为核心的语言特性考虑在内。并且,线程等并发模型在不同平台之上也有各种不同的实现,构建一个统一的并发模型也很困难。

C++11中重新设计了C++的内存模型,在保持原有兼容性的基础之上加入了并发的内容。同时标准库中也加入了线程(<thread>)、信号量(<condition_variable>)、互斥锁(<mutex>)和原子操作(<atomic>)等内容。同时也在此基础上封装了future/promise模式和async等操作。

元编程

C++自身对元编程提供了良好的支持。作为主要组件之一的模版,提供了编译时的数值计算和类型计算。但一方面由于使用模版减慢编译速度,另一方面,在使用模版的时候,非常难以调试和排错,这让很多人望而却步,甚至对基于模版的STL组件也有一种畏惧感。

C++11中对元编程支持做了加强。首先是把type traits作为标准库引入,能够给模版提供一套直观的约束,也让类型作为C++中的第一类值(first-class value)存在;另外constexpr的引入简化了编译时的值运算,配合用户自定义字面量(user-defined literals)以及可变参数模版(varadic template/parameter pack)等特性,让C++能够更方便地定义内部DSL。

Bright Future

作为一门经典的编程语言,C++至今还在不断地更新着。即将到来的C++17中,正在筹备着这些重要的特性:

  • 更丰富的标准库:C++中对File System、Network等重要的组件进行了标准化的支持,
  • Module TS:模块化提案,用于替代继承自C语言的头文件,简化C++的编译模型和模块依赖,
  • Concepts TS:用于增强类型约束和类型推导,同时也简化模版的用法,
  • Reflection TS:提供编译期静态反射的支持,简化和增强type traits,提供更丰富的元编程功能。

Conclusion

可以看到C++发展至今一直都走在时代的前列线上。一方面,增加了更多适合应用和系统开发的组件,另一方面,通过语言特性的扩充来简化抽象复杂度。作为这样一个兼具新生特性和历史责任的编程语言,足以预见其应用的广度;同样,更多的系统级开源项目,像Mesos等,也选择C++作为主要的编程语言。有足够的理由让我们相信,C++正在重获新生。

原文发布于微信公众号 - 思特沃克(ThoughtWorks)

原文发表时间:2015-12-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

编程语言中间令人无语的规则

我们都知道,软件开发人员每天都在做各种各样的决策:如何更好地实现功能、如何修复bug、如何改进应用程序性能等等。但是他们也在其他人的工作成果中继续自己的决定,例...

37750
来自专栏ThoughtWorks

都100%代码覆盖了,还会有什么问题?

(图片来自:http://t.cn/R06rQHi) 引言 很多人看到这个标题时,都会想“你都100%代码覆盖了,怎么还会有问题呢?” 让我们看一下代码例子:...

39780
来自专栏上善若水

007尝试使用UML图

尝试使用uml图来帮助自己快速的构建稳健的程序 uml对理清自己的思路,应该是很有帮助的了

11720
来自专栏web前端教室

《一个陌生同学的留言》-- “老尚,你一定要讲设计模式”

image.png 以前就曾经有人问过我,“老尚,你说是不是有的面试官以虐新人为乐?”,,,我说,“传说中,据说有”,,,他说,“我觉得这应该不是传说。” //...

20880
来自专栏程序员的知识天地

JavaScript编程趋势:用map和filter替换forEach

当你需要拷贝一个数组的全部或者部分到一个新数组的时候,优先使用map和filter而不是forEach。

14730
来自专栏微信公众号:Java团长

软件开发之技能梳理

摘要:根据我的开发实践及理解,梳理了作为软件工程师解决现实问题应当具备的基础技能。

12920
来自专栏非著名程序员

编程内功心法:如何写代码?

写代码就是学一门语言然后开始撸代码吗?看完了我的《GoF 设计模式》系列文章的同学或者本身已经就是老鸟的同学显然不会这么认为。编程是一项非常严谨的工作!

700130
来自专栏北京马哥教育

据说这篇总结覆盖了一般Python开发面试中可能会问到的大部分问题

先介绍下我的情况 通信背景,工作一年多不到两年。之前一直在做C++的MFC软件界面开发工作。公司为某不景气的国企研究所。(喏,我的工作经验很水:1是方向不对;...

42090
来自专栏牛客网

多篇面经集合,你不容错过的干货!

  5. 写一个单例模式,答主写的是双检查锁单例,问了为什么用 Volatile,synchronize 移到 方法最外面会怎么样?

14020
来自专栏技术翻译

Python逻辑编程实例

逻辑编程是一种编程范例,它将计算视为对事实和规则构成的知识数据库的自动推理。它是一种编程方式,基于形式逻辑。这种语言的程序是一组逻辑形式的句子,表达关于问题域的...

40830

扫码关注云+社区

领取腾讯云代金券