C++ - Copy constructor with pointers as the data field - c++

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();

Related

less-than operator doesn't work properly after few executions

I'm a beginner to learning C++. Just today I tried to learn the boolean operator and if-else statement.
This is the code:
int main(){
//if-else statement
int a, b;
bool result = (a < b);
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result <<std::endl;
if(result == true){
std::cout << a << " is less than " << b << std::endl;
}
if(!(result == true)){
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}
These are the results after a few executions:
Initially the results were fine, but then after a couple times it went wrong.
Does anybody know what the cause of this is?
Your mistake is that you compare the two variables and save the result before you assign any proper values to these variables. In other words, you compare uninitialized variables a and b which have undefined values.
First, you do:
bool result = (a < b);
And then after you get the values:
std::cin >> a;
std::cin >> b;
You should do the following instead:
// ...
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = a < b; // <-- move this down here!
// ...
You expect result to be evaluate a == b when you use it later. Instead bool result = (a < b); initializes result with (a < b) once and its value does not change afterwards. As neither a nor b are initialized when you declare result your code has undefined behavior.
You can make result a function object to make it work as you expected by using a lambda expression. However, to call it you'll have to add ():
int main(){
//if-else statement
int a = 0;
int b = 0;
auto result = [&](){ return a < b; };
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result() <<std::endl;
if(result()) {
std::cout << a << " is less than " << b << std::endl;
} else {
std::cout << a << " is NOT less than " << b << std::endl;
}
}
You should always initialize variables. Using the value of uninitialized variables is undefined behavior and can happen easily (as in your code) when you do not initialize variables. Instead of if (condition) {} if (!condition){} you can use if (condition) {} else {}. Instead of if (result() == true) you can write if (result()). And return 0; is implicit in main, you need not write it.
You overall code as it should be.
Explanations in the comments:
int main() {
//if-else statement
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = (a < b); // put this here, because now a and b have
// determined values
std::cout << std::boolalpha << result << std::endl;
if (result) { // or simple if (a < b) and drop result alltogether
std::cout << a << " is less than " << b << std::endl;
}
else { // no need for testing the opposite of result
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}

Parameterized constructor for assignment

I've noticed some behaviour which I can't understand in parameterized constructors. Given the following program:
#include <iostream>
using namespace std;
class A {
public:
int x;
A() {}
A(int i) : x(i){
cout << "A\n";
}
~A(){
cout << "dA\n";
}
};
int main(){
A p;
p = 3;
cout << p.x << endl;
p = 5;
cout << p.x << endl;
return 0;
}
I get as output:
A
dA
3
A
dA
5
dA
This means that using = triggers the parameterized constructor, destroys the object on which it's called and creates a new object.
I cannot understand this behaviour and I can't find the answer in the standard ( I am sure it is there somewhere, but it may be stated in a sophisticated way). Could someone help me with an explanation?
The phrase you're probably looking for is "implicit conversion".
If you add a copy constructor and an assignment operator, and then give each object a unique ID, it's easier to see where things go:
int counter = 0;
class A {
public:
int id;
A(): id(++counter) {cout << "A(): " << id << "\n";}
A(int i) : id(++counter) {cout << "A(" << i << "): " << id << "\n";}
// Don't copy the id.
// (This isn't used anywhere, but you can't see that it's not used unless it exists.)
A(const A& a) : id(++counter) {cout << "A(" << a.id << "): " << id << "\n";}
// Don't copy the id here either.
A& operator=(const A&a) {cout << id << " = " << a.id << "\n"; return *this;}
~A(){cout << "destroy: " << id << "\n";}
};
int main(){
A p;
cout << "p is " << p.id << "\n";
p = 3;
cout << "p is " << p.id << "\n";
p = 5;
cout << p.id << "\n";
}
Output:
A(): 1
p is 1
A(3): 2
1 = 2
destroy: 2
p is 1
A(5): 3
1 = 3
destroy: 3
1
destroy: 1
As you can see, the parameterized constructor is used to create a temporary object whose value can be assigned to p, and that temporary is destroyed immediately after that.
You can also see that p is alive and well until the very end.
With a statement like
p = 3;
what you're actually doing is
p = A(3);
which really translates to
p.operator=(A(3));
The temporary A object created by A(3) of course needs to be destructed, it is temporary after all.
The object p itself will not be destructed by the assignment.

How are two different inherited pointer addresses equal?

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)

Order of constructor and destructor calling?

I cannot understand the order of constructor and destructor calls? What will execute first in this statement A b=f(a)? Can someone please help me out?
#include<iostream>
using namespace std;
class A {
int x;
public:
A(int val = 0)
:x(val) {
cout << "A " << x << endl << flush;
}
A(const A& a) {
x = a.x;
cout << "B " << x << endl << flush;
}
void SetX(int x) {
this->x = x;
}
~A() {
cout << "D " << x << endl << flush;
}
};
A f(A a) {
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
int main()
{
A a(1);
A b=f(a);
b.SetX(-100);
return 0;
}
Output Window:
A 1
B 1
C
B 100
D 100
D -100
D 1
Why does it print B 1 in line 2 of the output window?
"Why does it print B 1 in line 2?"
Because the copy constructor was called from this statement
A b=f(a);
The function f() requires A being passed by value, thus a copy for this parameter is made on the function call stack.
If your next question should be, how you can get over this behavior, and avoid to call the copy constructor, you can simply pass the A instance as a reference to f():
A& f(A& a) {
// ^ ^
cout << " C " << endl << flush;
a.SetX(100);
return a;
}
Side note: endl << flush; is redundant BTW, std::endl includes flushing already.

Precedence of operators?

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.