在 if 条件内声明变量有什么问题?

发布于 2024-12-28 02:57:00 字数 421 浏览 1 评论 0原文

也许我已经生疏了(最近一直在用Python编写)。

为什么这不能编译?

if ( (int i=f()) == 0)

如果没有 () 周围的 int i=f() 我得到另一个更合理的错误 i is not being boolean。但这就是为什么我首先想要括号!

我的猜测是,使用括号将其放入表达式中,并且表达式中不允许使用声明语句。是这样吗?如果是的话,这是 C++ 的语法怪癖之一吗?

顺便说一句,我实际上是想这样做:

if ( (Mymap::iterator it = m.find(name)) != m.end())
    return it->second;

Perhaps I am getting rusty (have been writing in Python recently).

Why does this not compile?

if ( (int i=f()) == 0)

without the () around the int i=f() I get another, much more reasonable error of i is not being boolean. But that's why I wanted the parentheses in the first place!

My guess would be that using the parentheses makes it into an expression, and that declaration statements are not allowed in an expression. Is it so? And if yes, is it one of the C++'s syntax quirks?

BTW, I was actually trying to do this:

if ( (Mymap::iterator it = m.find(name)) != m.end())
    return it->second;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

回梦 2025-01-04 02:57:00

您可以在 C++ 中的 if 语句中声明变量,但它仅限于直接初始化,并且需要转换为布尔值:

if (int i = f()) { ... }

C++ 没有任何可以描述为“声明表达式”,即声明变量的[子]表达式。

实际上,我只是查了一下标准中的条款,根据 6.4 [stmt.select] 第 1 段,两种形式的初始化都支持:

...
condition:
   expression
   attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
   attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list
...

也就是说,也可以写:

if (int i{f()}) { ... }

显然,这仅适用于 C++2011因为C++2003没有大括号初始化。

You can declare a variable in the if statement in C++ but it is restricted to be used with direct initialization and it needs to convert to a Boolean value:

if (int i = f()) { ... }

C++ doesn't have anything which could be described as "declaration expression", i.e. [sub-] expressions declaring a variable.

Actually, I just looked up the clause in the standard and both forms of initialization are supported according to 6.4 [stmt.select] paragraph 1:

...
condition:
   expression
   attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
   attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list
...

That is, it is also be possible to write:

if (int i{f()}) { ... }

Obviously, this only works in C++2011 because C++2003 doesn't have brace-initialization.

动次打次papapa 2025-01-04 02:57:00

范围有问题。

考虑以下代码:

if ((int a = foo1()) || (int b = foo2()))
{
    bar(b);
}

b 是否在块内声明?如果 foo1() 返回 true 会怎样?

There's a problem with scope.

Consider the following code:

if ((int a = foo1()) || (int b = foo2()))
{
    bar(b);
}

Is b declared inside the block? What if foo1() returns true?

鸵鸟症 2025-01-04 02:57:00

您可以在 if 语句(或在 for 或 while 中)声明变量,但只能在外括号块中声明,并且它需要能够转换为 bool。

您的猜测基本上是正确的,这是不允许的,因为

(int i = 42;)

不是带有初始化的有效声明。

你需要额外的一行,

Mymap::iterator it;
if ( (it = m.find(name)) != m.end())
    return it->second;

但最好写成

Mymap::iterator it = m.find(name);
if ( it != m.end() ) 
    return it->second;

You can put the return line after the if,如果你真的想要这行回来,至少对我来说这不会不会损害可读性,但其他人可能会认为不同。

如果您真的非常想声明一个迭代器并在 if 条件中将其用作 bool ,您可以这样做,

if ( struct { int it; operator bool() { return it != m.end; } } s = { m.find(name) } )
    return s.it->second;

但我认为这有害;-)

You can declare a variable in an if statement (or in for or while), but only in the outer parenthesis block and it needs to be able to be converted to bool.

Your guess is basically right, it's not allowed because

(int i = 42;)

is not a valid declaration with initialization.

You need one additional line,

Mymap::iterator it;
if ( (it = m.find(name)) != m.end())
    return it->second;

but then it's better to write

Mymap::iterator it = m.find(name);
if ( it != m.end() ) 
    return it->second;

You can put the return line after the if, if you really want this line back, at least for me this doesn't harm readability, but others might see that different.

If you really, really want to declare an iterator and use the it as bool in an if condition, you could do

if ( struct { int it; operator bool() { return it != m.end; } } s = { m.find(name) } )
    return s.it->second;

but I would consider this harmful ;-)

初与友歌 2025-01-04 02:57:00

确实,你不会写,

if ( (int i=f()) == 0)

但你可以完美地写

if ( int i=f())

所以你可以使用 && 运算符在一个语句中执行这两个操作,例如

if ( int i=1 && (i=f()) == 0)

i 应该初始化为0 以外的任何值,如果您的编译器应用从左到右的计算,则它应该是第一个条件。

但不幸的是,正如第二个示例所要求的那样,这不适用于迭代器。

It's true that you can't write

if ( (int i=f()) == 0)

but you can perfectly write

if ( int i=f())

So you can use the && operator to perform both operations in one statement like

if ( int i=1 && (i=f()) == 0)

i should be initialized with any value other than 0, and it should be the first condition if your compiler applies left-to-right evaluation.

But unfortunately, that's not applicable in case of iterators as your second example asks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文