在C ++中,您可以在if语句中初始化变量,如下所示:
if (CThing* pThing = GetThing())
{
}
为什么会考虑这种糟糕或好的风格?有什么好处和坏处?
我个人喜欢这种风格,因为它限制了pThing变量的范围,因此当它为NULL时永远不会意外使用它。但是,我不喜欢你不能这样做:
if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}
如果有办法完成上述工作,请发帖。但如果那是不可能的,我仍然想知道原因。
答案 0 :(得分:19)
重要的是C ++中的声明不是表达式。
bool a = (CThing* pThing = GetThing()); // not legit!!
你不能在if语句中同时使用声明和布尔逻辑,C ++语言规范特别允许表达式或声明。
if(A *a = new A)
{
// this is legit and a is scoped here
}
我们如何知道a是否在表达式中的一个术语和另一个术语之间定义?
if((A *a = new A) && a->test())
{
// was a really declared before a->test?
}
咬紧牙关并使用内部if。范围规则很有用,您的逻辑是明确的:
if (CThing* pThing = GetThing())
{
if(pThing->IsReallySomeThing())
{
}
}
答案 1 :(得分:4)
关于优势:
始终建议您在第一次需要时定义变量,而不是之前的行。这是为了提高代码的可读性,因为无需滚动和搜索定义的位置就能知道CThing是什么。
同样将范围缩小为循环/ if块,导致变量在执行代码块后被取消引用,这使其成为垃圾收集的候选者(如果语言支持此功能)。
答案 2 :(得分:3)
if (CThing* pThing = GetThing())
错误的样式,因为在if
内你没有提供布尔表达式。您正在提供CThing*
。
CThing* pThing = GetThing();
if (pThing != NULL)
这是一种很好的风格。
答案 3 :(得分:2)
这个 应该 在C ++ 中不起作用,因为即使它支持short circuiting evaluation。 也许不要尝试以下方法:
if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}
错误..请参阅Wesley Tarle's answer
答案 4 :(得分:2)
我通常不这样做的一个原因是因为条件测试中错过了'='的常见错误。我使用带有错误/警告设置的lint来捕获它们。然后它会对条件内的所有作业大喊大叫。
答案 5 :(得分:2)
仅仅是一个FYI一些较旧的Microsoft C ++编译器(我认为Visual Studios 6和.NET 2003)在某些情况下并不完全遵循范围规则。
for(int i = 0; i > 20; i++) {
// some code
}
cout << i << endl;
我应该超出范围,但那是/是有效的代码。我认为它是作为一个功能播放的,但在我看来,它只是不合规。不遵守标准是不好的。就像关于IE和Firefox的网络开发者一样。
有VS的人可以查看是否仍然有效吗?
答案 6 :(得分:1)
自 C ++ 17 起,您可以在if
和switch
中包含初始化语句。
您的代码现在为:
if (CThing* pThing = GetThing(); pThing->IsReallySomeThing())
{
// use pThing here
}
// pThing is out of scope here
答案 7 :(得分:0)
您还可以将分配括在一个额外的()集中,以防止出现警告消息。
答案 8 :(得分:0)
我认为这有点危险。下面的代码更加安全,封闭的括号仍将以您希望的方式限制pThing的范围。
我假设GetThing()有时会返回NULL,这就是为什么我把这个有趣的子句放在if()语句中。它可以防止在NULL指针上调用IsReallySomething()。
{
CThing *pThing = GetThing();
if(pThing ? pThing->IsReallySomeThing() : false)
{
// Do whatever
}
}
答案 9 :(得分:0)
另请注意,如果您正在编写C ++代码,那么您希望在条件语句(这不是声明的一部分)中使编译器警告“=”错误。
答案 10 :(得分:0)
这是可以接受和良好的编码实践。但是,不是来自低级编码背景的人可能不同意。
答案 11 :(得分:0)
这么多东西。首先,裸指针。请一定避免它们。使用references,optional,unique_ptr,shared_ptr。作为最后的手段,编写自己的类来处理指针所有权,而不是别的。
如果你需要C ++ 11(首选C ++ 14以避免C ++ 11缺陷),请使用统一初始化: - 它避免了= vs ==混淆,并且在检查参数时更严格是的。
if (CThing thing {})
{
}
确保实施operator bool
以获得从CThing到bool的可预测转换。但请注意,阅读代码的其他人不会立即看到operator bool
。显式方法调用通常更具可读性和令人放心。如果您可以要求C ++ 17,请使用初始化程序语法。
if (CThing thing {}; thing.is_good())
{
}
如果C ++ 17不是一个选项,请使用上面的声明,如同其他人所建议的那样。
{
CThing thing {};
if (thing.is_good())
{
}
}