Can a variable be defined only in the scope of an

2019-01-28 11:54发布

问题:

Is there a way to declare, assign and compare a variable to an expression in an if construction in such a way that it is only defined in the scope of the if construction?

This works (declare and assign, but of course the condition is only the return value of function f being equal to zero or not):

int main()
{
  if(int i = f())
  {
    printf("%d", i);
    // i is defined here!
  }
  else
  {
    // Here too!
  }
  // But not here!
}

But when I try to compare the value of i with an actual expression I run into trouble:

int main()
{
  // Does not compile because "int i = f()" is not a primary expression?
  if((int i = f()) == 3)
  {
    printf("%d", i);
  }
}

Creating a scope around the whole if construction kind of does the trick, from a behavior point of view, but it looks ugly in my opinion:

int main()
{
  {
    int i = f();
    if(i == 3)
    {
      printf("%d", i);
      // i is defined here!
    }
    // here too!
  }
  // i is not defined here!
}

I'm comparing with the look and feel of for-loops and switches where it's so neat to declare and assign a variable so it is only defined in the scope in question. Of course the value of the variable is not compared to anything there and i'm not saying it's the same thing:

for(int i = 0;;)
{
  break;
}
// i is not defined here

switch(int i = f())
{
  default: break;
}
// i is not defined here!

So to sum it up, is there a way to tie the definition of a variable to the scope of "if" in a similar way as it's commonly tied to the scope of for and (perhaps not as commonly) switch, and where you actually compare the value of the variable to an expression as the condition of the if-statement?

回答1:

As far as I can tell there is no way to have both a declaration and an expression within the condition of an if statement. If we look at the draft C++ standard section 6.4 Selection statements the grammar for if is as follows:

selection-statement:
    if ( condition ) statement
    if ( condition ) statement else statement
    switch ( condition ) statement
condition:
    expression
    attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
    attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list

So you either can use an expression or a declaration and I don't see any obvious ways around that.

What you proposed in the alternative, declaring i before the if statement seems like the best option. Although using an enclosing block does not seem necessary:

int i = f();
if(i == 3)


回答2:

You can declare the variable in the if, but if you do so, the condition depends on the implicit conversion of the type to bool, which is very limiting and a bit obfuscating. The definition in the for works because the first part of the for isn't part of the condition. Just write:

int i = f();
if ( i == 3 ) {
    //  ...
} else {
    //  ...
}

This leaves the variable in scope until the end of the enclosing block, but the enclosing block can't be bigger than the entire function; if leaving it in scope is a problem, then your functions are too large and complex, and need to be refactored.



回答3:

You can only do a declaration OR boolean logic in an if statement. The C++ spec says so somewhere, forgot where exactly. Therefore a code like: if (int x = 3 && x == 3) {} will never compile because it will also throw the error that x is used uninitialized



回答4:

The first snippet works because you are declaring and defining i in if's conditional expression. It will always evaluated to true.
The second snippet does not compile because you are comparing a non-primary (because i is declared and defined here) expression in conditional expression with a primary expression.