受RAII思想影响比较深的我,一直认为如果程序组织的好,你通常是不需要编写析构函数的(析构通常用于资源的释放,如果你的类使用的资源都是RAII管理的话,通常也就不需要自己编写析构函数了)。但是因为过于迷恋这一点,2017-02-15我写出了一个坑了很久的BUG。
捉妖记
DEBUG是程序员的日常生活,有些BUG看到现象的瞬间你就知道问题出在哪里,而有些BUG则
隐藏的极深,让人百思不得其解,这些BUG我称之为妖
,解这种BUG则美其名为捉妖
,这
个系列的文章里面记录了自己曾经遇到过的各种妖
,起名捉妖记。
读书札记之——《Effective Modern C++》
光看作者Scott Meyers
就知道这会是一本好书,可惜的是目前在国内只有影印版。还是梅
耶熟悉的味道——唠唠叨叨,但是问题讲的很详细,有条有理。关于C++11之前读过《深入理
解C++11 : C++ 11新特性解析与应用》一书,大概了解了新的特性,于是就开始疯狂的迷恋
新的语法特性,看完梅耶的书之后,感觉一直以来很多东西我都是门外汉,不懂装懂到处宣
扬,也就难免误人子弟了。
讲了什么
这本书对C++11/C++14中的很多特性做了比较详细的讨论,主要讲解的内容包括auto
类型
推导,智能指针的使用,移动语义的使用,lambda 表达式的使用等等。这本书让我理解了
很多之前一直困惑的概念,梅耶也许不是对知识理解最透彻的人,但他很可能是讲解最清晰
的人,只要你能忍受他偶尔的唠叨。
没讲什么
一直以来我都觉得梅耶对于C++语言的阐述更加偏向于OO,这本书关于泛型的内容有所增加 ,但是我依旧觉得少了一些泛型编程的ITEM,比如如何使用可变参数模板等等。此外这本书 对于标准库的讲解偏少,只是简单的提了一下并发的内容。
std::bind 的实现原理
C++11 中有一个非常神奇的函数std::bind
,它让你可以对函数进行适配,动态的绑定参
数。比如你有一个函数接收两个参数,一个算法接收单参数的callable object
,那么通
过std::bind
我们可以让两者协同工作。
1 | void Foo(int a, int b); |
那么这个神奇的 bind
函数和神奇的占位符到底是怎么实现的呢,它们的工作原理是什么
?这个问题困扰我很久,最近在网上找到一篇讲解非常清晰的文章,这里对其中的
内容做简单的摘要和翻译,希望对于大家理解背后的工作原理会有帮助。
enable_shared_from_this 的使用及实现原理
本文除 boost 源码以外,大部分源码都是伪代码,为了能够更清晰的理解问题,去掉了 模板相关的内容。文中很多地方直接使用了 sp 一词表示 shared_ptr
使用智能指针难以避免的场景之一就是需要把 this 当成一个 shared_ptr 传递到其他函数 中去。比如你的类实现了某个接口,而你需要把自己注册为该接口的实现。你不能简单粗暴 的用 this 指针构造一个 shared_ptr,因为那样做会导致两个独立的 shared_ptr 指向同 一份资源,这对于基于引用计数的 shared_ptr 来说是致命的。比如下面的代码。
1 | class Widget { |
正确的打开方式是继承来自 std::enable_shared_from_this,然后调用它的 shared_from_this 成员函数
1 | class Widget : public std::enable_shared_from_this<Widget> { |
把自己作为基类的模板参数看起来非常诡异,它有一个更诡异的名字——奇异递归模板模式。 关于它的使用这里不过多的介绍,有兴趣的同学可以参考《More Effective C++》,《C++ Templates》等书籍。这里主要探讨的是它是如何实现返回自身的智能指针的。
读书札记之——《GNU Autoconf, Automake and Libtool》
之前看过Alexandre Duret-Lutz
的《Using GNU Autotools》,对于 autotools 的使用并
不陌生,但是总是觉得自己对于这些工具的理解非常的模糊,很多时候都只是停留在知其然
不知其所以然的层面。这是我为什么读《GNU Autoconf, Automake and Libtool》这本书的
原因。这本书是我无意间在 google 上漫游的时候搜索到的,这本书我只看了前面几个章节
,后面的内容过于索然无味,弃之。
autotool 的由来
autotool 主要包含三个工具,autoconf、automake、libtool。这些工具之所以会出现和
unix
的发展有很大的关系。unix
发展初期因为授权问题出现了大量的版本,而这些版
本中提供的库函数各不相同,却又大同小异。想要编写在各个版本中都可移植的程序非常困
难。为了解决这个问题才出现了autoconf
这一类的软件,它们的本质实际上是帮你探测不
同的系统的属性,也就是告诉你哪个功能有,哪个功能没有之类的。这一点让我想起
JavaScript发展初期的时候遇到的同样的问题,各种浏览器支持的特性各不相同,想要写一
个跨浏览器的脚本同样非常困难。这从一个侧面反映出一个标准的重要性。
autoconf
可以帮助你写出款平台编译的程序,而automake
则主要是帮你更好的完成跨
平台编译这件事情。编译需要用到各种编译器命令,因为不想手动的执行这些命名出现了
Makefile
,又因为不想手动的编写Makefile
出现了automake
这类的工具,它让你可以
只提供源文件的名称便替你生成 Makefile,这也着实省下不少的麻烦。
程序库的发展过程中首先出现的是静态库,实际上只是.o
的打包而已。后来出现了更高级
的动态库,可惜的是和之前一样,这些动态库在不同的系统上实现是不一样的,为了能够跨
平台的生成这些程序库,也就有了libtool
这类的工具。
前面的介绍中,我使用的词语都是这类的
,因为这种工具其实上出现过很多种,只是到了
最后慢慢的统一成了目前我们看到的这几个,他们最终合起来被称为autotools
。
做一个实用主义者
不要尝试去写一个可以运行在一切平台的configure
脚本,实用为主,如果你只需要在
Linux
上运行,又何苦去测试Windows
才有的功能呢?
configure.in,configure.ac 结构
通常应该按照下面的顺序编程一个configure.ac
文件:
- 引用 AC_INIT,AM_INIT_AUTOMAKE,AC_CONFIG_HEADER 等等
- 选项,比如:AC_ARG_ENABLE
- 程序检测,比如:AC_CHECK_PROG
- 库的检测
- 头文件检测
- typedefs 和 结构体的检测
- 函数的检测
- 输出:AC_OUTPUT
2017 年书单
去年这个时候,我给自己列了一份书单,可惜的是其中超过半数的书籍我都没有看完,尤其 是非技术类的书籍。参加工作后的自己少了很多的阅读时间,但是我还是希望自己可以坚持 看书的习惯。所以依旧打算给你开一份新年的书单,新年的书单以务实为主,只打算列出每 月一本的量,希望年底的时候,这些书籍都已经读完。
技术书籍
- autobook
- Effective Morden C++
- 像计算机科学家一样思考Python
- C++ 沉思录
- 编写可读代码的艺术
- 泛型编程与STL
- 代码整洁之道
- STL源码剖析
- 高级 C/C++ 编译技术
- 重构
- 计算机程序的构造和解释
- 敏捷软件开发(原则模式与实践)
- 高效程序员的45个习惯:敏捷开发修炼之道
- 编程人生
- UNIX 编程艺术
- 代码大全
- 图解TCP/IP
- 图解HTTP