Look at this simple class:
class A {
int *val;
public:
A() { val = new int; *val = 0; }
int get() { return ++(*val); }
};
Why when I run this code it prints 21:
int main() {
A a, b = a;
cout << a.get() << b.get();
return 0;
}
But if I run it like this it prints 12 which is what I was expecting:
int main() {
A a, b = a;
cout << a.get();
cout << b.get();
return 0;
}
What am I missing here? Operator precedence? FYI, this is a C++ test problem, not a production code.
EDIT:
Does it means that when I have cout << (Expr1) << (Expr2) then Expr1 and Expr2 are evaluated before the output of Expr1 is printed?
Operator precedence does not dictate the order of evaluation of intermediate results. I.e. it does not dictate the order of evaluation of sub-expressions in the entire expression.
Expression statement
cout << a.get() << b.get();
can be executed by the compiler as
int tmp_a = a.get();
int tmp_b = b.get();
cout << tmp_a;
cout << tmp_b;
or as
int tmp_b = b.get();
int tmp_a = a.get();
cout << tmp_a;
cout << tmp_b;
In this case operator precedence and associativity for operator << guarantees that tmp_a is sent to output before tmp_b. But it does not guarantee that tmp_a is evaluated before tmp_b.
This line:
cout << a.get() << b.get();
does not specify whether a.get() or b.get() is evaluated first.
Since a and b share the same val pointer, the order of those operations affect the output.
(Edit)
Does it means that when I have cout << (Expr1) << (Expr2) then Expr1 and Expr2 are evaluated before the output of Expr1 is printed?
That is also not specified.
Related
This question already has answers here:
C++, variable declaration in 'if' expression
(8 answers)
Closed 3 years ago.
I wanted to be able to do multiple assignments in an if block and short-circuit if the first one fails. However, this does not compile and says, expected primary-expression before ‘auto’
#include <iostream>
#include <optional>
std::optional<int> foo()
{
return 0;
}
int main() {
if (auto a = foo() && auto b = foo())
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
The following works though and does what I want.
if (auto a = foo())
{
if (auto b = foo()) {
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
But is there a way for me to use the syntax in the first one? Using parenthesis to surround the expressions does not work.
Since C++17, you could write
if (decltype(foo()) a, b; (a = foo()) && (b = foo()))
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
But if you want to see the short circuit in action, you should change the condition:
#include <iostream>
#include <optional>
std::optional<int> foo()
{
std::cout << "foo called.\n";
return 1;
}
int main()
{
if (decltype(foo()) a, b; (a = foo()) or (b = foo()))
{
// For exposition only ^^
std::cout << "a = " << *a << ", b = " << *b << std::endl;
// Note that, now, this is UB ^^
}
}
Compare the output of this
foo called.
a = 1, b = 0
Versus the former.
It has nothing to do with auto. Declarations cannot be part of an expression. You can either use an expression or a single declaration inside an if statement.
So even this will not compile:
#include <iostream>
int foo()
{
return 0;
}
int main()
{
if (int a = foo() && int b = foo())
{
std::cout << "a = " << a << ", b = " << b << std::endl;
}
return 0;
}
Edit: In C++17 you can have an initializer statement before the condition statement, like so: if (auto a = foo(), b = foo(); a && b). However that will not give you short circuiting.
The only way I see is that you reformulate (without declaring the variables inside the if condition):
#include <iostream>
#include <optional>
std::optional<int> foo()
{
return 0;
}
int main() {
std::optional<int> a , b;
if ((a = foo()) && (b = foo()))
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
See a working example here please.
Since c++17 you can even do the variable declarations inside the if condition like this:
if (std::optional<int> a , b; (a = foo()) && (b = foo()))
Though usage of auto isn't possible in that case.
Another live demo.
Consider these codes:
int a = 5;
int b = a++;
cout << "b is " << b << endl; // b is 5
or:
int get_number(){
int a = 5;
return a++;
}
int main(){
int b = get_number();
cout << "b is " << b << endl; // b is 5
}
According to this table postfix ++ operator has higher precedence than = operator so the output should be b is 6. but the output is b is 5. How can we explain this?
The contract of the postfix++ operator (and postfix-- operator) for built-in types is that it returns the previous value, irrespective of the change that takes place. So the function still returns 5, even if the variable which received the change is assigned 6 afterwards.
As per expr.post.incr, emphasis mine:
The value of a postfix ++ expression is the value of its operand. [ Note: The value obtained is a copy of the original value — end note ]
The value computation of the ++ expression is sequenced before the
modification of the operand object. With respect to an
indeterminately-sequenced function call, the operation of postfix ++
is a single evaluation
int a = 5;
int b = a++; // the value computation for a is
// the non-modified / non-incremented value
// which is 5
std::cout << "a is " << a << std::endl; // a is 6
std::cout << "b is " << b << std::endl; // b is 5
After reading C++: Comparing pointers of base and derived classes, I thought for sure this wouldn't work.
When I executed this, the printed addresses for c_as_b and &c were different, so why does this print "seems safe to compare pointers in same hierarchy"? What is being compared besides the printed addresses that could result in true?
Can you give a similar small example where the == results in false?
#include <iostream>
using namespace std;
struct A { std::string s; };
struct B { int i; };
struct C : A, B { double d; };
int main() {
C c;
B* c_as_b = &c;
A* c_as_a = &c;
cout << "c_as_a: " << c_as_a << endl
<< "c_as_b: " << c_as_b << endl
<< "&c: " << &c << endl;
cout << (c_as_b == &c ? "seems safe to compare pointers in same hierarchy" : "definately not safe") << endl;
return 0;
}
Sample output:
c_as_a: 0xbfb98f10
c_as_b: 0xbfb98f14
&c: 0xbfb98f10
seems safe to compare pointers in same hierarchy
The pointer equality comparison c_as_b == &c will do an implicit pointer conversion. From [expr.eq]:
If at least one of the operands is a pointer, pointer conversions (4.10), function pointer conversions (4.12),
and qualification conversions (4.4) are performed on both operands to bring them to their composite pointer
type (Clause 5).
Basically, &c will be converted to a B* so that the comparison can happen. At which point, it is exactly the same as c_as_b (since that's how you got that pointer to begin with), so they compare equal.
In this example, c is statically upcast to B, and then compared with c_as_b yielding true.
To answer the part of the question that nobody touched on: Can you give a similar small example where the == results in false?
Here is a similar example where the == results in false, using dynamic_cast<void*> makes the same comparison true, and commented out is a way that == results in a compile time error:
#include <iostream>
using namespace std;
struct A { virtual ~A() {} };
struct B : A { };
struct C : A { };
struct D : B, C { };
int main() {
D d;
C* c = &d;
B* b = &d;
A* a_through_b = b; // &d results in error: 'A' is an ambiguous base of 'D'
A* a_through_c = c;
cout << "&d: " << &d << endl
<< "c : " << c << endl
<< "b : " << b << endl
<< "a_through_b : " << a_through_b << endl
<< "a_through_c : " << a_through_c << endl;
cout << (a_through_b == a_through_c ? "a_through_b == a_through_c" : "a_through_b != a_through_c") << endl;
cout << (dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c) ? "dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)" : "dynamic_cast<void*>(a_through_b) != dynamic_cast<void*>(a_through_c)") << endl;
//cout << (a_through_c == &d) << endl; // error: 'A' is an ambiguous base of 'D'
cout << (dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d) ? "dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)" : "dynamic_cast<void*>(a_through_c) != dynamic_cast<void*>(&d)") << endl;
return 0;
}
Sample output:
&d: 0xbff6d558
c : 0xbff6d55c
b : 0xbff6d558
a_through_b : 0xbff6d558
a_through_c : 0xbff6d55c
a_through_b != a_through_c
dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)
dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)
I have the following code :-
#include <iostream>
using namespace std;
class A {
int *val;
public:
A() { val = new int; *val = 0; }
int get() { return ++(*val); }
};
int main() {
A a,b = a;
A c,d = c;
cout << a.get() << b.get() ;
cout << endl ;
cout << c.get() << endl ;//
cout << d.get() << endl;
return 0;
}
It produces the output as :-
21
1
2
The behavior in case of c.get and d.get is easy to understand.
Both c and d share the same pointer val and a and b share the same pointer val.
So c.get() should return 1 and d.get() should return 2.
But I was expecting similar behavior in a.get() and b.get(). (maybe I have not understood cout properly)
I am unable to understand how a.get() is producing 2.
Can you explain why I am getting such an output. According to me the output should have been :-
12
1
2
cout << a.get() << b.get() ;
gets executed as:
cout.operator<<(a.get()).operator<<(b.get());
In this expression, whether a.get() gets called first or b.get() gets called first is not specified by the language. It is platform dependent.
You can separate them into two statements to make sure they get executed in an expected order.
cout << a.get();
cout << b.get();
#include <iostream>
using namespace std;
class Array
{
private:
int* a;
int n;
public:
Array(int n) : n(n) {a = new int[n];};
~Array(){delete a;};
int& operator[](int i)
{
try
{
if ( i < 0 || i >= n) throw 1;
return a[i];
}
catch(int i)
{
cout << "Exception Array" << endl;
return a[0];
}
};
};
int main()
{
Array a(2);
try
{
a[0] = 1;
cout << "a[0]=" << a[0] << endl;
a[1] = 1;
cout << "a[1]=" << a[1] << endl;
a[2] = 2;
cout << "a[2]=" << a[2] << endl;
}
catch(int i)
{
cout << "Exception main " << endl;
}
cout << "End. " << endl;
}
Okay, so the output is this:
a[0]=1
a[1]=1
Exception Array
Exception Array
a[2]=2
End.
The thing that is confusing me is the reasoning why the program is returning
a[2] as value 2? Can someone go into more detail as to how this is achieved, step by step. I think I am not understanding something about exceptions in C++.
a[2] = 2;
Here you invoke your operator[] with an out-of-bounds value; it prints Exception Array and returns a reference to a.a[0]. As such (ignoring the log message), this assignment is equivalent to a[0] = 2; - the value of a.a[0] is now 2.
cout << "a[2]=" << a[2] << endl;
Here you again invoke the operator[] with the same parameter; it again outputs the exception message and returns a reference to a.a[0] whose value is still 2, as assigned in the previous statement.
This code
a[2] = 2;
cout << "a[2]=" << a[2] << endl;
tries to access a[2] twice, once in the assignment and once in the output statement. They are both out of range, so two exceptions.