Strange behavior when initializing template structure - c++

I have a structure:
template < class L, class R > struct X {
X()
{ }
friend std::ostream& operator<<(std::ostream& str, X& __x)
{
return str << '(' << __x.__val1 << ", " << __x.__val2 << ')';
}
private:
L __val1;
R __val2;
};
and create it without initializing anything:
X<std::size_t, std::string> x;
std::cout << x << std::endl;
It always gives output: (2, )
But, when i do:
X<std::string, std::size_t> x;
std::cout << x << std::endl;
I have "right" behaviour with uninitialized variable: (, 94690864442656).
Why?

There is no "right" value of an uninitialized variable.
The value is said to be "indeterminate". Using an indeterminate value leads to undefined behavior. Your program could output anything or nothing.
Assuming (, 94690864442656) to be "right", because it looks like some "uninitialized value" while (2, ) looks like something was initialized, is wrong.
2 is just as wrong as 94690864442656. When the behavior of your code is undefined, then it is undefined.
If it helps, think of it like this: You are supposed to calculate the result of 2*3. Instead of actually carrying out the calculation you call the number that comes to your mind in that moment. Most of the time you will say the wrong result. Once in a while you will answer with a result that looks meaningful, because you correctly guessed 6, or you said 5 or 7 which is just off by one. However, getting the expected result sometimes, does not imply that your way of getting the result is correct.
Or consider this: (but be careful with the use of randomness here. Uninitialized values are not random!) Suppose instead of calculating the result of 2*3 you use the wrong way of rolling a dice (instead of actually calculating the number). Now assume you roll a 6. Would you be surprised to get the "correct" result, even though your algorithm is wrong?
If you really care why you get 2 in one case and 94690864442656 in the other, you need to study the assembly generated by the compiler, because C++ does not specify what is the outcome of compiling code with undefined behavior. It just says: It is undefined.
Note that also using identifiers that contain a double underscore is not allowed, as such names are reserved (https://en.cppreference.com/w/cpp/language/identifiers).

Related

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.

Problem assigning a value to an "adjacent" variable

Here in this code, I have first described int a and assigned value 9 to it and then I declared another int b and then I have given value 3 to *(&b-1) so (&b-1) refers to &a and then I printed the value of a then it prints 9 only but when I add new line in the code(line no. 6) i.e. first printed a and then assigned value 3 to (&b-1) then it updates a to 3 and prints it. So why it's happening like this?
#include <iostream>
using namespace std;
int main() {
double a, b;
a = 9;
//cout<<&a<<" "<<a << endl ;
*(&b - 1) = 3;
cout << a << " " << &b - 1 << " ";
cout << &a;
}
so (&b-1) refers to &a
No, that's not how C++ works.
You can't "navigate" the stack frame like this, because C++ is an abstraction and does not have stack frames.
What you're doing here is pretending that b is a pointer to the second (or later) element of an array, and trying to get the value of the preceding element in that array. As we know, you do not actually have an array.
So why it's happening like this?
That's why. You lied to the compiler, and now it's freaking out.
Yes, it really does care about this kind of thing!
Your question is based on a false premise
[...] (&b-1) refers to &a [...]
Thats wrong. So when you ...
*(&b - 1) = 3;
you are dereferencing a pointer that you are not allowed to dereference. There is no double stored at (&b - 1). As this is undefined behaviour your program can do anything and thats about as much as one can say about your code ;).

References, Logical Operators, and Loop Condition

I'm having a problem understanding what I'm doing wrong in my code. What I'm trying to do is write a condition for a ternary operator and a do-while loop to recognize if one of my variables is above 1. Well, it is giving me an error that I don't know how to fix. What puzzles me the most is what I'll give an example of shortly. Here's my overall code. Keep in mind I'm a beginner, so there may be things that make you cringe or parts that could be improved.
#include <iostream>
using namespace std;
void getInfo(int&, int&, double&);
int main() {
int ordered, stock;
double charges = 10.00;
getInfo(ordered, stock, charges);
system("pause");
return 0;
}
void getInfo(int& ordered, int& stock, double& charges) {
do {
printf("Enter the amount of spools ordered, in stock, and handling charges: ");
scanf_s("%i %i %lf", &ordered, &stock, &charges);
printf((&ordered > 1 && &stock > 0 && &charges > 0) ? "All added!\n"
: "You messed one up. AGAIN!\n");
} while (&ordered > 1 && &stock > 0 && &charges > 0);
}
Now, the error I'm getting is specifically in the ternary and the while condition. It gives me an error where the > is after ordered for both. Now, if I make it ordered instead of &ordered, the error goes away. Yet, I never get an error for &stock or &charges. I don't know why it's treating &ordered differently. It also doesn't check ordered correctly when I take off the &, for reasons I'm not entirely sure on.
Thank you to whomever is willing to help!
...(&ordered > 1 && &stock > 0 && &charges > 0) ? "All added!\n"
Here, "&ordered" means "the address of the ordered variable. You're obviously not trying to compare the address of ordered, but rather ordered itself. This should be
...(ordered > 1 && stock > 0 && charges > 0) ? "All added!\n"
The same problem is with your while() statement too.
In C++, "&" means two things. In declarations, it's used to declare a reference. In expression, it's the "address of" operator.
Once you declare a reference, like:
int &whatever;
Subsequently, using just whatever refers to the referenced object itself.
: "You messed one up. AGAIN!\n");
The & operator does different things depending on where you put it. If it's in a type declaration (e.g. int& foo), it means that the type is a reference. If however the & is used as an unary operator in an expression it becomes the Address-of operator, and returns a pointer to the object it's used on. So for example int* bar = &spam (assuming spam is an integer) would assign a pointer to spam in in the pointer bar.
Note that reference types behaves identical to the real type. This is perhaps better illustrated with a piece of code:
#include <iostream>
int main() {
int foo = 12;
int& bar = foo; // a reference expects a variable of the same type in the initializer
bar = 24; // Once the reference has been made the variable behaves indentically to the
// to the variable it's a reference to.
std::cout << foo << std::endl; // outputs 24
// if you use the & operator on a reference you get the address the variable it is a
// reference to.
std::cout << &bar << ' ' << &foo << std::endl; // Outputs two equal addresses.
}
There is also a third meaning of & in C++. As the bitwise and operator. foo & bar would result in the bitwise and of the variable foo and bar.

Why are string::append operations behaving strangely?

look at the following simple code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("1234567890");
string::iterator i1 = s.begin();
string::iterator i2 = s.begin();
string s1, s2;
s1.append(i1, ++i1);
s2.append(++i2, s.end());
cout << s1 << endl;
cout << s2 << endl;
}
what would you expect the output to be?
would you, like me, expect it to be:
1
234567890
wrong!
it is:
234567890
i.e. the first string is empty.
seams that prefix increment operator is problematic with iterators. or am I missing something?
You're missing something: this really has nothing to do with iterators. The order in which arguments to a function are evaluated is unspecified. As such your: append(i1, ++i1); would depend on unspecified behavior, regardless of the type of i1. Just for example, given something a lot simpler like:
void print(int a, int b) {
std::cout << a << " " << b << "\n";
}
int main() {
int a =0;
print(a, ++a);
return 0;
}
Your output could perfectly reasonably be the "0 1" you seem to expect, but it could also perfectly reasonably be: "1 1". Since this is unspecified, it could change from one version of the compiler to the next, or even with the same compiler when you change flags, or (in theory) could vary depending on the phase of the moon...
C++ implementations are free to evaluate arguments in any order. In this case, if ++i1 is evaluated first, you will get an empty string.
Not a bug.
The order in which the arguments to
s1.append(i1, ++i1);
are evaluated is not specified by the standard. The compiler is free to use any order it chooses. In this case, it evaluates the second argument (++i1) before the first (i1) and you specify a null range to copy.
The C++ standard does not specify anything about the order in which the function arguments are evaluated, making it implementation dependent. C++ requires that the arguments to a function be completely evaluated (and all side-effects posted) prior to entering the function, but the implementation is free to evaluate the arguments in any order
In your case i++ got evaluated before making both the parameters same, resulting in an empty string.
More info on this behavior here on comp.compilers newsgroup

C++ Output evaluation order with embedded function calls

I'm a TA for an intro C++ class. The following question was asked on a test last week:
What is the output from the following program:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}
The answer, to me and all my colleagues, is obviously:
8
27
64
But now several students have pointed out that when they run this in certain environments they actually get the opposite:
64
27
8
When I run it in my linux environment using gcc I get what I would expect. Using MinGW on my Windows machine I get what they're talking about.
It seems to be evaluating the last call to myFunc first, then the second call and then the first, then once it has all the results it outputs them in the normal order, starting with the first. But because the calls were made out of order the numbers are opposite.
It seems to me to be a compiler optimization, choosing to evaluate the function calls in the opposite order, but I don't really know why. My question is: are my assumptions correct? Is that what's going on in the background? Or is there something totally different? Also, I don't really understand why there would be a benefit to evaluating the functions backwards and then evaluating output forward. Output would have to be forward because of the way ostream works, but it seems like evaluation of the functions should be forward as well.
Thanks for your help!
The C++ standard does not define what order the subexpressions of a full expression are evaluated, except for certain operators which introduce an order (the comma operator, ternary operator, short-circuiting logical operators), and the fact that the expressions which make up the arguments/operands of a function/operator are all evaluated before the function/operator itself.
GCC is not obliged to explain to you (or me) why it wants to order them as it does. It might be a performance optimisation, it might be because the compiler code came out a few lines shorter and simpler that way, it might be because one of the mingw coders personally hates you, and wants to ensure that if you make assumptions that aren't guaranteed by the standard, your code goes wrong. Welcome to the world of open standards :-)
Edit to add: litb makes a point below about (un)defined behavior. The standard says that if you modify a variable multiple times in an expression, and if there exists a valid order of evaluation for that expression, such that the variable is modified multiple times without a sequence point in between, then the expression has undefined behavior. That doesn't apply here, because the variable is modified in the call to the function, and there's a sequence point at the start of any function call (even if the compiler inlines it). However, if you'd manually inlined the code:
std::cout << pow(x++,3) << endl << pow(x++,3) << endl << pow(x++,3) << endl;
Then that would be undefined behavior. In this code, it is valid for the compiler to evaluate all three "x++" subexpressions, then the three calls to pow, then start on the various calls to operator<<. Because this order is valid and has no sequence points separating the modification of x, the results are completely undefined. In your code snippet, only the order of execution is unspecified.
Exactly why does this have unspecified behaviour.
When I first looked at this example I felt that the behaviour was well defined because this expression is actually short hand for a set of function calls.
Consider this more basic example:
cout << f1() << f2();
This is expanded to a sequence of function calls, where the kind of calls depend on the operators being members or non-members:
// Option 1: Both are members
cout.operator<<(f1 ()).operator<< (f2 ());
// Option 2: Both are non members
operator<< ( operator<<(cout, f1 ()), f2 () );
// Option 3: First is a member, second non-member
operator<< ( cout.operator<<(f1 ()), f2 () );
// Option 4: First is a non-member, second is a member
cout.operator<<(f1 ()).operator<< (f2 ());
At the lowest level these will generate almost identical code so I will refer only to the first option from now.
There is a guarantee in the standard that the compiler must evaluate the arguments to each function call before the body of the function is entered. In this case, cout.operator<<(f1()) must be evaluated before operator<<(f2()) is, since the result of cout.operator<<(f1()) is required to call the other operator.
The unspecified behaviour kicks in because although the calls to the operators must be ordered there is no such requirement on their arguments. Therefore, the resulting order can be one of:
f2()
f1()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or:
f1()
f2()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or finally:
f1()
cout.operator<<(f1())
f2()
cout.operator<<(f1()).operator<<(f2());
The order in which function call parameters is evaluated is unspecified. In short, you shouldn't use arguments that have side-effects that affect the meaning and result of the statement.
Yeah, the order of evaluation of functional arguments is "Unspecified" according to the Standards.
Hence the outputs differ on different platforms
As has already been stated, you've wandered into the haunted forest of undefined behavior. To get what is expected every time you can either remove the side effects:
int myFunc(int &x) {
int temp = x * x * x;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x+1) << endl << myFunc(x+2) << endl;
//Note that you can't use the increment operator (++) here. It has
//side-effects so it will have the same problem
}
or break the function calls up into separate statements:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
}
The second version is probably better for a test, since it forces them to consider the side effects.
And this is why, every time you write a function with a side-effect, God kills a kitten!