我的意思是除了在函数,类,if,while,switch,try-catch需要时使用它。
我不知道可以像this until I saw this SO question那样完成。
在上面的链接中,Eli提到“他们使用它来将代码折叠成逻辑部分,这些逻辑部分不属于通常会折叠起来的函数,类,循环等。”
除了上面提到的那些还有什么其他用途?
使用花括号来限制变量的范围并仅在需要时扩展范围(在“需要访问”的基础上工作)是不是一个好主意?或者它真的很傻?
如何使用范围,以便您可以在不同的范围内使用相同的变量名,但是在相同的更大范围内?或者,重用相同的变量(如果你想使用相同的变量名)是更好的做法,并节省解除分配和分配(我想一些编译器可以对此进行优化?)?或者更好地使用不同的变量名称?
答案 0 :(得分:49)
如果我正在使用我想在特定时间释放的资源,我会这样做,例如:
void myfunction()
{
{
// Open serial port
SerialPort port("COM1", 9600);
port.doTransfer(data);
} // Serial port gets closed here.
for(int i = 0; i < data.size(); i++)
doProcessData(data[i]);
etc...
}
答案 1 :(得分:39)
出于某种原因,我不会为此目的使用花括号。
如果你的特定功能足够大,你需要做各种范围的技巧,可能会将功能分解成更小的子功能。
引入大括号以便重用变量名称只会导致代码混乱和麻烦。
只需2美分,但我在其他最佳实践材料中看到了很多这类东西。
答案 2 :(得分:16)
我经常使用的范围最常见的“非标准”使用范围是使用范围的互斥锁。
void MyClass::Somefun()
{
//do some stuff
{
// example imlementation that has a mutex passed into a lock object:
scopedMutex lockObject(m_mutex);
// protected code here
} // mutex is unlocked here
// more code here
}
这有很多好处,但最重要的是即使在受保护的代码中抛出异常,也会始终清除锁定。
答案 3 :(得分:15)
<强> C ++ 强>:
有时你需要引入一个额外的大括号范围,以便在有意义时重用变量名称:
switch (x) {
case 0:
int i = 0;
foo(i);
break;
case 1:
int i = 1;
bar(i);
break;
}
上面的代码无法编译。你需要做到:
switch (x) {
case 0:
{
int i = 0;
foo(i);
}
break;
case 1:
{
int i = 1;
bar(i);
}
break;
}
答案 4 :(得分:11)
正如其他人所说,最常见的用途是确保析构函数在您需要时运行。使特定于平台的代码更加清晰也很方便:
#if defined( UNIX )
if( some unix-specific condition )
#endif
{
// This code should always run on Windows but
// only if the above condition holds on unix
}
为Windows构建的代码不会看到if,只有大括号。这比以下更清楚:
#if defined( UNIX )
if( some unix-specific condition ) {
#endif
// This code should always run on Windows but
// only if the above condition holds on unix
#if defined( UNIX )
}
#endif
答案 5 :(得分:6)
它可以成为代码生成器的福音。假设您有一个嵌入式SQL(ESQL)编译器;它可能希望将SQL语句转换为需要局部变量的代码块。通过使用块,它可以反复使用固定变量名,而不必使用单独的名称创建所有变量。当然,这不是太难,但它比必要的更难。
答案 6 :(得分:6)
正如其他人所说,由于功能强大的RAII(资源获取是初始化)习惯用法/模式,这在C ++中相当普遍。
对于Java程序员(也许是C#,我不知道),这将是一个外国概念,因为基于堆的对象和GC会杀死RAII。恕我直言,能够将对象放在堆栈上是C ++相对于Java的最大单一优势,并使编写良好的C ++代码比编写良好的Java代码更清晰。
答案 7 :(得分:5)
我只在需要通过RAII释放某些内容时使用它,即使只是在我尽可能早地释放它时(例如释放锁定)。
答案 8 :(得分:3)
用Java编程我经常想在一个方法中限制范围,但我从未想过使用标签。由于我在使用它们作为休息目标时将我的标签大写,因此使用像你所建议的标记块的混合大小写就是我在这些场合所需要的。
通常代码块太短而不能分解成一个小方法,而且通常是框架方法中的代码(如startup()或shutdown()),实际上最好将代码保存在一个方法中。
就我个人而言,我讨厌普通的漂浮/悬挂支架(虽然那是因为我们是一个严格的横幅式缩进商店),我讨厌评论标记:
// yuk!
some code
{
scoped code
}
more code
// also yuk!
some code
/* do xyz */ {
scoped code
}
some more code
// this I like
some code
DoXyz: {
scoped code
}
some more code
我们考虑使用“if(true){”,因为Java规范明确指出这些将在编译时被优化掉(if(false)的整个内容也是如此 - 这是一个调试功能),但我讨厌它我试过的几个地方。
所以我觉得你的想法很好,一点也不傻。我一直认为我是唯一一个想要这样做的人。
答案 9 :(得分:1)
是的,我使用这种技术是因为RAII。我也在普通的 C 中使用这种技术,因为它使变量更加接近。当然,我应该考虑更多地分解这些功能。
我做的一件事可能是风格上有争议的,就是在声明的行上加上开头的大括号,或者对它进行评论。 I want to decrease the amount of wasted vertical space. This is based on the Google C++ Style Guide recommendation.
/// c++ code
/// references to boost::test
BOOST_TEST_CASE( curly_brace )
{
// init
MyClass instance_to_test( "initial", TestCase::STUFF ); {
instance_to_test.permutate(42u);
instance_to_test.rotate_left_face();
instance_to_test.top_gun();
}
{ // test check
const uint8_t kEXP_FAP_BOOST = 240u;
BOOST_CHECK_EQUAL( instance_to_test.get_fap_boost(), kEXP_FAP_BOOST);
}
}
答案 10 :(得分:0)
我同意agartzke。如果您认为需要对较大的逻辑代码块进行细分以提高可读性,则应考虑重构以清理繁忙且混乱的成员。
答案 11 :(得分:0)
它有它的位置,但我不认为这样做,以便$ foo可以是一个变量 here 和一个不同的变量那里,在同一个函数中或其他(逻辑的,而不是词汇的)范围是一个好主意。尽管编译器可能完全理解这一点,但似乎很可能让人类试图阅读代码变得困难。
答案 12 :(得分:0)
我正在工作的公司有一个静态分析策略,可以将局部变量声明保留在函数的开头附近。很多时候,在函数的第一行之后使用很多行,所以我无法在屏幕上同时看到声明和第一个引用。我所做的“规避”策略是将声明保持在引用附近,但通过使用花括号提供额外的范围。但它会增加缩进,有些人可能会认为它会使代码变得更加丑陋。