在今天阅读proggit时,我在一篇文章中发表了这篇评论,关于Google Ai挑战中的顶级位置是如何被C++采用的.用户reventlov声明
我在C++中遇到的最大问题是,如果没有真正理解使用C++可以理解的所有需要,那么你很容易认为自己是"C++程序员".
您必须了解RAII,并且知道使用命名空间,并了解正确的异常处理(例如,您应该能够解释为什么STL中的pop()方法不返回它们删除的值).您必须知道标准库中的三代函数中哪一个是正确的.您应该熟悉PIMPL等概念.您需要了解标准库(尤其是STL)的设计是如何工作的.您需要了解宏如何与命名空间交互,以及为什么通常不应该在C++中使用宏,以及应该使用什么(通常是模板或内联,很少是类).你需要了解提升.
我想我是他提到的那些无能的C++程序员之一.为了简短起见,我的问题是
我会回答第2点,其余的留给其他人.pop不返回删除值的主要原因是异常安全.
首先,要了解C++容器(不像Java的那些容器)按值保存它们的对象.这意味着如果您希望容器在弹出时返回对象,则必须通过复制要删除的对象按值返回该对象.相反,通过top以前访问pop,它可以简单地返回对顶部元素的引用,并且可以在弹出它之前将其复制到心脏的内容.(然而,如果pop通过引用返回元素,它将是一个悬空引用,因为对象不再在容器中.)
做的后果pop由价值回归(除了参与复制被删除对象的低效率)是它危及异常安全.理想情况下,如果操作抛出异常,则所涉及对象的状态不变.但是如果pop要按值返回被删除的对象,那么该对象的复制构造函数如何失败呢?该对象已经从容器中删除,因此状态已经改变.
这比我想做的更有语言,但希望能让你知道为什么pop返回一个值是一个坏主意.
一个很好的例子,其中RAII是至关重要但有时被遗忘的是锁定互斥锁时.如果您有一段锁定互斥锁的代码,执行操作,然后将其解锁,如果操作抛出异常或导致线程死亡,则互斥锁保持锁定状态.这就是为什么有几种范围的锁类(比如QMutexLocker因为作为陈述)在这里,你保证析构函数会运行.因此,如果您使用范围锁定,它将始终在销毁时解锁以防止死锁.
void为了速度,Pop返回:SGI FAQ,以及防止对象复制构造函数可能抛出的异常.
Qt框架大量使用PIMPL来提供二进制兼容性.它允许您从公共API隐藏数据结构的所有内部.这意味着,如果要将私有成员添加到类中,则将其添加到d指针.这保持了二进制代码兼容性,因为暴露的唯一数据成员是指针.