你最喜欢的C ++编码风格成语是什么?
你最喜欢的C ++编码风格习语是什么? 我正在问风格或编码排版,比如放置大括号的位置,关键字后面是否有空格,缩进大小等等。这与最佳做法或要求相反,例如总是使用delete[]
删除数组。
下面是我最喜欢的一个例子:在C ++类初始化程序中,我们把分隔符放在行的前面,而不是后面。 这可以更容易地保持最新状态。 这也意味着版本之间的源代码控制差异更为清晰。
TextFileProcessor::
TextFileProcessor( class ConstStringFinder& theConstStringFinder )
: TextFileProcessor_Base( theConstStringFinder )
, m_ThreadHandle ( NULL )
, m_startNLSearch ( 0 )
, m_endNLSearch ( 0 )
, m_LineEndGetIdx ( 0 )
, m_LineEndPutIdx ( 0 )
, m_LineEnds ( new const void*[ sc_LineEndSize ] )
{
;
}
在创建枚举时,将它们放在一个名称空间中,以便可以使用有意义的名称访问它们:
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(范围绑定资源管理)。
也可以看看:
复制交换
复制交换语言提供了异常安全的复制。 它要求执行正确的拷贝和交换。
struct String {
String(String const& other);
String& operator=(String copy) { // passed by value
copy.swap(*this); // nothrow swap
return *this; // old resources now in copy, released in its dtor
}
void swap(String& other) throw() {
using std::swap; // enable ADL, defaulting to std::swap
swap(data_members, other.data_members);
}
private:
Various data_members;
};
void swap(String& a, String& b) { // provide non-member for ADL
a.swap(b);
}
您也可以直接使用ADL(参数相关查找)实现交换方法。
这个成语很重要,因为它处理自我分配[1],做出强有力的例外保证[2],并且通常很容易编写。
[1]即使自我分配没有尽可能有效地处理,但它应该是罕见的,所以如果它从不发生,这实际上更快。
[2]如果抛出任何异常,则该对象的状态( *this
)不会被修改。