你最喜欢的C++编码风格习惯是什么?
创建枚举时,应该将它们放在一个命名空间中,这样就可以使用有意义的名称访问它们:
namespace EntityType { enum Enum { Ground = 0, Human, Aerial, Total }; } void foo(EntityType::Enum entityType) { if (entityType == EntityType::Ground) { /*code*/ } }
注意:然而,在C++11中,这种技术已经过时。应该使用带作用域的枚举(使用enum class
或enum struct
声明),它更加类型安全、简洁和灵活。与旧式枚举不同,值被放置在外部范围。在新式枚举中,它们被放置在enum class
名称的范围内。
使用带作用域的枚举(也称为强类型枚举)重写的上面的示例:
enum class EntityType { Ground = 0, Human, Aerial, Total }; void foo(EntityType entityType) { if (entityType == EntityType::Ground) { /*code*/ } }
使用带作用域的枚举有其他显着的好处:没有隐式转换,可能的前向声明以及使用自定义底层类型(而不是默认的int
)。
RAII: 资源获取即初始化
RAII可能是最重要的惯用语。它的思想是资源应该映射到对象上,以便根据声明这些对象的范围自动管理它们的生命周期。
例如,如果在堆栈上声明一个文件句柄,则一旦从函数(或循环或声明它的任何范围)返回,它应该隐式关闭。如果动态内存分配是作为类的成员分配的,则在该类实例被销毁时应隐式释放。等等。每种资源-内存分配,文件句柄,数据库连接,套接字以及任何其他必须获取和释放的资源-都应该包装在这样的RAII类中,其生命周期由声明它的范围确定。
这样做的一个重要优点是,C++保证在对象超出范围时调用析构函数,无论控件如何离开该范围。即使抛出异常,所有局部对象也会超出范围,因此其关联的资源将得到清理。
void foo() { std::fstream file("bar.txt"); // open a file "bar.txt" if (rand() % 2) { // if this exception is thrown, we leave the function, and so // file's destructor is called, which closes the file handle. throw std::exception(); } // if the exception is not called, we leave the function normally, and so // again, file's destructor is called, which closes the file handle. }
无论如何离开函数以及文件开放后发生了什么事情,我们都不需要在函数内部显式关闭文件或处理异常(例如try-finally)。相反,该文件被清理,因为它与一个本地对象绑定,该对象在超出其作用域时被销毁。
RAII也较少被称为SBRM(范围绑定资源管理)。
另请参见:
- ScopeGuard允许代码“在抛出异常的情况下自动调用'撤消'操作...”