Why is initialization of a new variable by itself valid? [duplicate] - c++

This question already has answers here:
What's the behavior of an uninitialized variable used as its own initializer?
(3 answers)
Closed 4 years ago.
Consider some code:
#include <iostream>
int main()
{
using std::cout;
int a=3;
cout << "a="<<a<<"\n";
{
int a=a;
cout << "new a = " << a << "\n";
a=5;
cout << "a = " << a << "\n";
}
cout << "old a = " << a << "\n";
}
I'd expect it to print
a=3
new a = 3
changed a = 5
old a = 3
But what I get actually appears to say new a = 0 in the second line. I thought that it would work like initialization list in a class' constructor, where one can write like
C::C(int a) : a(a) {}
But for some reason this is different. First, removing the outer code completely doesn't result in a compilation error. So I assume that int a=a; is valid. Turning on all the compiler warnings leads to this:
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
int a=a;
So my question now: why is this syntax valid at all? Why doesn't the compiler say something like "undefined variable a"?

It's syntactically valid, since the variable's point of declaration comes before its initialiser, and the name is available anywhere after that point. This allows less dodgy initialisations like
void *p = &p;
which legitimately uses the name (but not the value) of the variable being initialised.
It's behaviourally invalid, since using the value of an uninitialised object gives undefined behaviour. That's not an error that requires diagnosis (since, in general, it can be difficult or impossible to analyse the program flow to see whether an object has been initialised), but as you note, many compilers will give a warning for straightforward cases like this.

Related

Why do recursive variable definitions compile in C++ [duplicate]

This question already has answers here:
What's the behavior of an uninitialized variable used as its own initializer?
(3 answers)
Closed 4 years ago.
Consider some code:
#include <iostream>
int main()
{
using std::cout;
int a=3;
cout << "a="<<a<<"\n";
{
int a=a;
cout << "new a = " << a << "\n";
a=5;
cout << "a = " << a << "\n";
}
cout << "old a = " << a << "\n";
}
I'd expect it to print
a=3
new a = 3
changed a = 5
old a = 3
But what I get actually appears to say new a = 0 in the second line. I thought that it would work like initialization list in a class' constructor, where one can write like
C::C(int a) : a(a) {}
But for some reason this is different. First, removing the outer code completely doesn't result in a compilation error. So I assume that int a=a; is valid. Turning on all the compiler warnings leads to this:
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
int a=a;
So my question now: why is this syntax valid at all? Why doesn't the compiler say something like "undefined variable a"?
It's syntactically valid, since the variable's point of declaration comes before its initialiser, and the name is available anywhere after that point. This allows less dodgy initialisations like
void *p = &p;
which legitimately uses the name (but not the value) of the variable being initialised.
It's behaviourally invalid, since using the value of an uninitialised object gives undefined behaviour. That's not an error that requires diagnosis (since, in general, it can be difficult or impossible to analyse the program flow to see whether an object has been initialised), but as you note, many compilers will give a warning for straightforward cases like this.

A obj(obj), What's happening behind the scenes? [duplicate]

This question already has answers here:
What's the behavior of an uninitialized variable used as its own initializer?
(3 answers)
Closed 4 years ago.
Consider some code:
#include <iostream>
int main()
{
using std::cout;
int a=3;
cout << "a="<<a<<"\n";
{
int a=a;
cout << "new a = " << a << "\n";
a=5;
cout << "a = " << a << "\n";
}
cout << "old a = " << a << "\n";
}
I'd expect it to print
a=3
new a = 3
changed a = 5
old a = 3
But what I get actually appears to say new a = 0 in the second line. I thought that it would work like initialization list in a class' constructor, where one can write like
C::C(int a) : a(a) {}
But for some reason this is different. First, removing the outer code completely doesn't result in a compilation error. So I assume that int a=a; is valid. Turning on all the compiler warnings leads to this:
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
int a=a;
So my question now: why is this syntax valid at all? Why doesn't the compiler say something like "undefined variable a"?
It's syntactically valid, since the variable's point of declaration comes before its initialiser, and the name is available anywhere after that point. This allows less dodgy initialisations like
void *p = &p;
which legitimately uses the name (but not the value) of the variable being initialised.
It's behaviourally invalid, since using the value of an uninitialised object gives undefined behaviour. That's not an error that requires diagnosis (since, in general, it can be difficult or impossible to analyse the program flow to see whether an object has been initialised), but as you note, many compilers will give a warning for straightforward cases like this.

What is the compiler doing with parameters vs without parameters? [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 4 years ago.
I have a non important question about compilers for C++. The following code outputs
1
2
3
and I can't figure out why. What difference does declaring it with empty parameters make to no parenthesis at all?
#include <iostream>
using namespace std;
int main()
{
int x;
cout << x << endl;
int y();
cout << y << endl;
int z(2);
cout << z << endl;
return 0;
}
The compiler is g++.
The 1st one, x is default initialized with indeterminate value, then cout << x leads to undefined behavior, means anything is possible.
Default initialization of non-class variables with automatic and dynamic storage duration produces objects with indeterminate values
The 2nd one, int y(); declares a function named y, which has no argument and returns int. For cout << y, y will decay to function pointer, which could convert to bool implicitly and then you'll get 1 (i.e. true. You can use std::boolalpha like std::cout << std::boolalpha << y to get the output true).
The 3rd one, z is direct initialized with value 2, then cout << z you'll get 2.
LIVE sample with clang, note all the warning messages the compiler gives.

Why does C++ allow to use a variable in its own initialization? [duplicate]

This question already has answers here:
What's the behavior of an uninitialized variable used as its own initializer?
(3 answers)
Closed 4 years ago.
Consider some code:
#include <iostream>
int main()
{
using std::cout;
int a=3;
cout << "a="<<a<<"\n";
{
int a=a;
cout << "new a = " << a << "\n";
a=5;
cout << "a = " << a << "\n";
}
cout << "old a = " << a << "\n";
}
I'd expect it to print
a=3
new a = 3
changed a = 5
old a = 3
But what I get actually appears to say new a = 0 in the second line. I thought that it would work like initialization list in a class' constructor, where one can write like
C::C(int a) : a(a) {}
But for some reason this is different. First, removing the outer code completely doesn't result in a compilation error. So I assume that int a=a; is valid. Turning on all the compiler warnings leads to this:
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
int a=a;
So my question now: why is this syntax valid at all? Why doesn't the compiler say something like "undefined variable a"?
It's syntactically valid, since the variable's point of declaration comes before its initialiser, and the name is available anywhere after that point. This allows less dodgy initialisations like
void *p = &p;
which legitimately uses the name (but not the value) of the variable being initialised.
It's behaviourally invalid, since using the value of an uninitialised object gives undefined behaviour. That's not an error that requires diagnosis (since, in general, it can be difficult or impossible to analyse the program flow to see whether an object has been initialised), but as you note, many compilers will give a warning for straightforward cases like this.

When are rvalue references to primitive integers short-lived or long-lived?

I have done some experimentation on rvalue references with the TDM-GCC 4.6.1 compiler and made some interesting observations that I cannot explain away with theories. I would like experts out there to help me explain them.
I have a very simple program that does not deal with objects but int primitives and that has defined 2 functions:
foo1 (returning a local variable by rvalue reference) and
foo2 (returning a local variable by value)
#include <iostream>
using namespace std;
int &&foo1();
int foo2();
int main()
{
int&& variable1 = foo1();
//cout << "My name is softwarelover." << endl;
cout << "variable1 is: " << variable1 << endl; // Prints 5.
cout << "variable1 is: " << variable1 << endl; // Prints 0.
int&& variable2 = foo2();
cout << "variable2 is: " << variable2 << endl; // Prints 5.
cout << "variable2 is still: " << variable2 << endl; // Still prints 5!
return 0;
}
int &&foo1() {
int a = 5;
return static_cast<int&&>(a);
}
int foo2() {
int a = 5;
return a;
}
It seems the value returned by foo1 and received by variable1 dies out after some time - perhaps, a brief period of some milliseconds. Notice that I have prevented cout from printing "My name is softwarelover" by commenting it out. If I allow that statement to run, the result is different. Instead of printing 5, 0 it prints 0, 0. Seems like it is because of the time-delay introduced by "cout << "My name is softwarelover." that 5 turns into 0.
Is the above how an rvalue reference is supposed to behave when referring to a primitive integer which a function returned by reference as opposed to return-by-value? By the way, why is it 0, why not garbage?
Notice also that variable2 never seems to die out, no matter how many times I print it with cout! variable2 refers to a primitive integer which a function returned by value, not return-by-reference.
Thanks.
Rvalue references are still just references. A reference to a function local variable is invalid after the function returns. You're lucky your rvalue reference is 5 for any time at all after the function call, because it is technically invalid after the function returns.
Edit: I'm expanding upon my answer, hoping that some people will find some extra detail useful.
A variable defined inside a function is a function local variable. The lifetime of that variable is limited to inside the function that it was declared in. You can think of it as being 'destroyed' when the function returns, but it's not really destroyed. If it's an object, then its destructor will be called, but the memory that held the variable is still there. Any references or pointers you had to that variable still point to the same spot in memory, but that memory has been re-purposed (or may be re-purposed at some indeterminate time in the future).
The old values (in your case '5') will still be there for a while, until something comes along and overwrites it. There is no way to know how long the values will still be there, and no one should ever depend on them still being there for any amount of time after the function returns. Consider any references (or pointers) to function local variables invalid once the function returns. Metaphorically, if you go knocking on the door you probably won't find the new tenant agreeable.