我在读c++老师的课堂笔记,他是这样写的:
使用缩进// OK
永远不要依赖运算符优先级-总是使用括号// OK
总是使用{}块-即使是单行//不可以,为什么??
Const对象在比较的左边// OK
对>= 0的变量使用unsigned,这是个不错的技巧
删除后将指针设置为NULL -双重删除保护//不错
第三种方法我不清楚:放一行进去能得到什么
A{…} ?
例如,下面这段奇怪的代码:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
将其替换为:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
使用第一个版本的好处是什么?
我必须承认,我并不总是在单行中使用{},但这是一种很好的练习。
假设你写的代码没有括号,看起来像这样:
For (int I = 0;I < 100;+ + i)
For (int j = 0;J < 100;+ + j)
DoSingleStuff ();
过了一段时间,你想在j循环中添加一些其他东西,你只是通过对齐来做,忘记添加括号。
Memory deallocation is faster. Let’s say you have a big scope and create big arrays inside (without new so they are on the stack). Those arrays are removed from memory just after you leave the scope. But it is possible that you use that array in one place and it will be on the stack for a while and be some kind of rubbish. As a stack have limited and quite small size, it is possible to exceed the stack size. So in some cases it is better to write {} to preventing that. Note that this is not for a single line, but for such situations:
if (...)
{
//SomeStuff...
{//we have no if, while, etc.
//SomeOtherStuff
}
//SomeMoreStuff
}
The third way to use is similar to the second. It is just not to make the stack cleaner, but to open some functions. If you use mutex in long functions usually it is better to lock and unlock just before accessing data and just after finishing reading/writing that. Note: This way is used if you have some of your own class or struct with a constructor and destructor to lock memory.
What is more:
if (...)
if (...)
SomeStuff();
else
SomeOtherStuff(); // Goes to the second if, but alignment shows it is on first...
总而言之,我不能说,总是使用{}的最佳方式是单行,但这样做并没有什么不好。
如果你编写的是编译代码,但是如果你的代码是被解释的,那么你的代码就会非常非常慢。非常轻微。
当你完成它时,最好将指针设置为NULL。
下面是一个例子:
A类行为如下:
分配一块内存
然后一段时间后,它删除这块内存,但不将指针设置为NULL
B类做以下事情
分配内存(在这个实例中,它得到的内存块恰好与类a删除的内存块相同)
在这一点上,类A和类B都有指向同一个内存块的指针,就类A而言,这块内存块不存在,因为它已经用完了。
考虑以下问题:
如果在类a中有一个逻辑错误,导致它写入现在属于类B的内存呢?
在这个特定的实例中,您不会得到一个糟糕的访问异常错误,因为内存地址是合法的,而类A现在有效地破坏了类B数据。
类B可能最终崩溃,如果它遇到意外值,当它崩溃时,很有可能,当问题出现在类a时,您将花费相当长的时间在类B中查找这个bug。
如果您已经将删除的内存指针设置为NULL,那么只要类A中的任何逻辑错误试图写入NULL指针,您就会得到一个异常错误。
如果您担心在指针第二次为NULL时使用双重删除会出现逻辑错误,那么可以为此添加assert。
我必须承认,我并不总是在单行中使用{},但这是一种很好的练习。
假设你写的代码没有括号,看起来像这样:
For (int I = 0;I < 100;+ + i)
For (int j = 0;J < 100;+ + j)
DoSingleStuff ();
过了一段时间,你想在j循环中添加一些其他东西,你只是通过对齐来做,忘记添加括号。
Memory deallocation is faster. Let’s say you have a big scope and create big arrays inside (without new so they are on the stack). Those arrays are removed from memory just after you leave the scope. But it is possible that you use that array in one place and it will be on the stack for a while and be some kind of rubbish. As a stack have limited and quite small size, it is possible to exceed the stack size. So in some cases it is better to write {} to preventing that. Note that this is not for a single line, but for such situations:
if (...)
{
//SomeStuff...
{//we have no if, while, etc.
//SomeOtherStuff
}
//SomeMoreStuff
}
The third way to use is similar to the second. It is just not to make the stack cleaner, but to open some functions. If you use mutex in long functions usually it is better to lock and unlock just before accessing data and just after finishing reading/writing that. Note: This way is used if you have some of your own class or struct with a constructor and destructor to lock memory.
What is more:
if (...)
if (...)
SomeStuff();
else
SomeOtherStuff(); // Goes to the second if, but alignment shows it is on first...
总而言之,我不能说,总是使用{}的最佳方式是单行,但这样做并没有什么不好。
如果你编写的是编译代码,但是如果你的代码是被解释的,那么你的代码就会非常非常慢。非常轻微。
我喜欢卢钦公认的答案。事实上,我经过艰苦的学习才知道他是对的,所以我总是使用大括号,即使是单行块。然而,就我个人而言,我在编写过滤器时做了一个例外,就像您在示例中所做的那样。这样的:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
在我看来很混乱。它将'for'循环和'if'语句分离为单独的操作,而实际上你的目的是一个操作:计算所有能被2整除的整数。在更有表现力的语言中,可以这样写:
j = [1..100].filter(_%2 == 0).Count
在缺少闭包的语言中,过滤器不能用单个语句表示,而必须是一个for循环,后面跟着一个if语句。然而,这仍然是程序员心中的一个动作,我相信这应该反映在代码中,如下所示:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
{
j++;
}
为了补充之前回答中非常明智的建议,我在重构一些代码时遇到的一个例子是:我正在修改一个非常大的代码库,从一个API切换到另一个API。第一个API调用设置Company Id,如下:
setCompIds( const std::string& compId, const std::string& compSubId );
而替换需要两次调用:
setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );
我开始使用正则表达式来改变这种情况,这非常成功。我们还通过样式传递代码,这确实使它更易于阅读。然后,在审查过程中,我发现在某些条件下,它正在改变:
if ( condition )
setCompIds( compId, compSubId );
:
if ( condition )
setCompId( compId );
setCompSubId( compSubId );
这显然不是我们所需要的。我不得不回到一开始,再次将替换处理为完全在一个块内,然后手动修改任何最终看起来愚蠢的东西(至少它不会是不正确的)。
我注意到style现在有了一个选项——add-括号,它允许你在没有括号的地方添加括号,如果你发现自己处于和我一样的位置,我强烈建议你这样做。