Hiding int variable name in C ++

Out of curiosity, I tried this code due to an interview question [*]

int main(int argc, char *argv[]) { int a = 1234; printf("Outer: %d\n", a); { int a(a); printf("Inner: %d\n", a); } } 

When compiling on Linux (both g ++ 4.6.3 and clang ++ 3.0), it outputs:

 Outer: 1234 Inner: -1217375632 

However, on Windows (VS2010), it prints:

 Outer: 1234 Inner: 1234 

The rationale would be that until the copy constructor of the second variable "a" has finished, the first variable "a" is still available. However, I'm not sure if this is standard behavior or just (more explicit) Microsoft quirk.

Any idea?

[*] Actual question:

How do you initialize a variable within a value region with an identical named variable in the content region without using a temporary or global variable?

 { // Not at global scope here int a = 1234; { int a; // how do you set this a to the value of the containing scope a ? } } 
+7
source share
5 answers

I looked at the standard, this is actually a gray area, but here are my 2 cents ...

3.1 Declarations and Definitions [basic.def]

  • An ad introduces names into translation units or re-advertiser names entered by previous announcements.

  • A declaration is a definition, except when [irrelevant cases] follow

3.3.1 Point of declaration

  • The declaration point for the name immediately after its full declaration and before its initializer (if any), except as indicated below [homing example].

  • A nonlocal name remains visible until the declaration point of the local name that hides it.

Now, if we assume that this is the declaration point of the internal 'a' (3.3.1 / 1)

 int a (a); ^ 

then the outer "a" should be visible to this point (3.3.1 / 2), where the inner "a" is defined.

The problem is that in this case, according to 3.1 / 2, the declaration is a definition. This means that you need to create an internal "a". Until then, I cannot understand from the standard whether the external β€œa” remains or not. VS2010 assumes that it is, and everything that falls into parentheses refers to the external area. However, clang ++ and g ++ treat this line as a case of self-determination, which leads to undefined behavior.

I'm not sure which approach is right, but I think VS2010 is more consistent: the outer area is visible until the inner β€œa” is completely created.

0
source

How do you initialize a variable within a value region with an identical named variable in the content region without using a temporary or global variable?

If the outer region cannot be explicitly specified, you cannot do this. You can explicitly specify the global scope, namespace scope, and class scope, but not the scope or block.


C ++ 11 [basic.scope.pdecl 3.3.2 p1:

The declaration point for the name immediately after its full declaration (section 8) and before its initializer (if any), except as noted below. [Example:

 int x = 12; { int x = x; } 

Here the second x is initialized with its own (undefined) value. -end example]

MSVC implements this example correctly, however, it implements it incorrectly when the initializer uses brackets instead of assignment syntax. There is an error filed about this when connecting to Microsoft.

Here is an example program with incorrect behavior in VS as a result of this error.

 #include <iostream> int foo(char) { return 0; } int foo(int) { return 1; } int main() { char x = 'a'; { int x = foo(static_cast<decltype(x)>(0)); std::cout << "'=' initialization has correct behavior? " << (x?"Yes":"No") << ".\n"; } { int x(foo(static_cast<decltype(x)>(0))); std::cout << "'()' initialization has correct behavior? " << (x?"Yes":"No") << ".\n"; } } 

C ++ contains the following note.

[Note. Operations with undefined values ​​can cause undefined behavior. -end note]

However, this note indicates that operations can cause undefined behavior, and not what they necessarily do. The above error report is related to the confirmation from Microsoft that this is an error, and not that the program launches undefined behavior.

Edit: And now I changed the example so that an object with an undefined value is used only in an invaluable context, and I believe that this absolutely eliminates the possibility of undefined on any platform, still showing an error in Visual Studio.

+10
source

How do you initialize a variable within a value region with an identical named variable in the content region without using a temporary or global variable?

If you want technical information on the wording, this is pretty easy. "Temporary" has a definite meaning in C ++ (see Β§12.2); any named variable you create is not temporary. Thus, you can simply create a local variable (which is not temporary) initialized with the correct value:

 int a = 1234; { int b = a; int a = b; } 

An even more reasonable possibility would be to use a variable reference in the outer scope:

 int a = 1234; { int &ref_a = a; int a = ref_a; } 

This does not create an additional variable at all - it simply creates an alias for the variable in the outer scope. Since the alias has a different name, we retain access to the variable in the external area without defining a variable (temporary or otherwise) for this. Many links are implemented as pointers inside, but in this case (at least using a modern compiler and optimization), I expect that this is not the case, that the alias will really be considered as another name related to the variable (and a quick test with VC ++ shows that it works this way - the generated assembler language does not use ref_a at all).

Another possibility on the same lines would look like this:

 const int a = 10; { enum { a_val = a }; int a = a_val; } 

This is somewhat similar to a link, except that in this case there is no room for an argument about whether a_val can be called a variable - it is absolutely not a variable. The problem is that an enumeration can only be initialized with a constant expression, so we must define the external variable as const for it to work.

I doubt that any of them is what the interviewer really did, but they all answer the question as indicated. The first (admittedly) purely technical information on definitions of terms. The second may be open to any argument (many think of references as variables). Although it limits the scope, there is no room for a question or argument for a third.

+6
source

What you do when you initialize the variable with yourself is undefined behavior. All of your test cases realized that this is not a fad. An implementation can also initialize a to 123456789 , and it will still be standard.

Update: Comments on this answer indicate that initializing a variable is not in itself an undefined behavior, but there is an attempt to read such a variable.

+2
source

How do you initialize a variable within a value region with an identical named variable in the content region without using a temporary or global variable?

You can not. Once the same name is declared, the external name is not available to the rest of the scope. You will need a copy or alias of an external variable, which means you will need a temporary variable.

I am surprised that even with the warning level hanging, VC ++ does not complain about this line:

 int a(a); 

Visual C ++ sometimes warns you about hiding a variable (perhaps only for members of derived classes). It's also usually nice to tell you that you use a value before it is initialized, which is what happens here.

Looking at the generated code, the internal a is initialized with the same value of the external a as what is left in the register.

+1
source

All Articles