18

在 C++ 中,您可以在 if 语句中初始化变量,如下所示:

if (CThing* pThing = GetThing())
{
}

为什么人们会认为这种不好或好的风格?有什么好处和坏处?

我个人喜欢这种风格,因为它限制了 pThing 变量的范围,所以当它为 NULL 时永远不会被意外使用。但是,我不喜欢你不能这样做:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

如果有办法使上述工作,请张贴。但如果那是不可能的,我仍然想知道为什么。

从这里借来的问题,类似的主题,但 PHP。

4

12 回答 12

20

重要的是 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())
    {
    }
}
于 2008-09-25T22:52:00.887 回答
4

关于优点:

始终建议在您第一次需要变量时定义变量,而不是之前的一行。这是为了提高代码的可读性,因为无需滚动和搜索定义的位置就可以知道 CThing 是什么。

还将范围缩小到循环/if 块,导致变量在代码块执行后未被引用,这使其成为垃圾收集的候选者(如果语言支持此功能)。

于 2008-09-25T22:34:49.523 回答
3
if (CThing* pThing = GetThing())

这是不好的风格,因为在里面if你没有提供布尔表达式。您正在提供一个CThing*.

CThing* pThing = GetThing();
if (pThing != NULL)

这是很好的风格。

于 2010-01-20T16:31:07.637 回答
2

这在 C++ 中应该不起作用,因为即使它支持短路评估也许不要尝试以下操作:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

错误..见韦斯利塔尔的回答

于 2008-09-25T22:27:09.387 回答
2

我通常不这样做的一个原因是因为在条件测试中错过了“=”的常见错误。我使用带有错误/警告设置的 lint 来捕获这些错误/警告。然后它会对条件句中的所有作业大喊大叫。

于 2008-09-25T22:33:21.680 回答
2

仅供参考,一些较旧的 Microsoft C++ 编译器(我认为是 Visual Studios 6 和 .NET 2003)在某些情况下并不完全遵循范围规则。

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

我应该超出范围,但那是/是有效的代码。我相信它是作为一个功能被玩弄的,但在我看来,这只是不合规。不遵守标准是不好的。就像一个关于 IE 和 Firefox 的 web 开发者。

有VS的人可以检查一下这是否仍然有效?

于 2008-09-25T22:39:18.017 回答
2

这么多的事情。首先,裸指针。请务必避免使用它们。使用引用、可选、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())
  {
  }
}
于 2018-05-07T20:37:56.780 回答
1

您可以在C++17if内部和switch之后使用初始化语句。

您的代码现在是:

if (CThing* pThing = GetThing(); pThing->IsReallySomeThing())
{
    // use pThing here
}
// pThing is out of scope here
于 2019-07-30T11:37:42.973 回答
0

您还可以将分配包含在一组额外的 ( ) 中以防止出现警告消息。

于 2008-09-25T22:39:45.317 回答
0

我认为这有点危险。下面的代码更安全,并且括号仍然会以您想要的方式限制 pThing 的范围。

我假设 GetThing() 有时会返回 NULL,这就是为什么我将那个有趣的子句放在 if() 语句中。它可以防止在 NULL 指针上调用 IsReallySomething()。

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}
于 2008-09-25T22:42:40.270 回答
0

另请注意,如果您正在编写 C++ 代码,您希望编译器在条件语句(不是声明的一部分)中警告“=”成为错误。

于 2008-09-25T22:57:07.363 回答
0

这是可以接受的良好编码实践。但是,不是来自低级编码背景的人可能会不同意。

于 2008-09-25T23:00:01.507 回答