confusing output - c++

Below given program prints x = 10 y = 0
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
but if we replace
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
with
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
output is x = 10 y = 20
Can anyone explain why this is happening?

When you return a plain object rather than a reference, you're returning a copy of the object on which you called the method. setY acts on that copy (which is a temporary), then the copy is destructed.
When you return a reference, all the calls operate on the same object, so you get the behavior you're looking for.

The first call to setX() returns a temporary copy of obj1 and the call to setY() modifies the temporary. Subsequent call to print() displays the state of obj1 and since in obj1 the y member variable was never modified it remains zero.
When you replace the return types with references, no temporary copy is made the both calls to setX() and setY() operate on obj.

Lets go back to basis about object oriented programming.
Lets use a metaphor - say a bus.
A bus has certain properties that can be changed - e.g. fuel.
So if you have a function (top up the fuel) you do not need a new bus that is exactly the same as the last one bit with a fuel tank that is full.
So going back to the original question.
Test setX(int a) { x = a; return *this; }
should read
void setX(int a) { x = a; }
etc.
You have the same object but the fuel may be topped up (or x in this case)

In the First case you are returning the object by value, Hence the copy of object will be created and returned.
So
obj1.setX(10) will return a copy of test and than .setY(20) will work on that copy thats why its effects are not on obj1 .
while in second case a reference to object is returned and hence .setY(20) will work on obj1 itself . Hence the output.

This pinter contain address of a object
In first case
in setx fun this pointer return x and and not free for return y value at simultaneously therfore he send copy of y not address of y.
In second case
This both function are different both have own this pointer
So they send address of both x and y

Related

return class by value or by reference

I was checking a book of c++ and the put a function that is designed to make the class functions cascadable. In this book they conventionally make function inside the class to return a reference of the class rather than the class value. I tested returning a class by value or by reference and they both do the same. What is the difference?
#include<iostream>
using namespace std;
/*class with method cascading enabled functions*/
class a{
private:
float x;
public:
a& set(float x){
this->x = x;
return *this;
}
a& get(float& x){
x = this->x;
return *this;
}
a print(){
cout << "x = " << x << endl;
return *this;
}
};
int main(){
a A;
A.set(13.0).print();
return 0;
}
result
PS J:\c-c++> g++ -o qstn question1.cpp
PS J:\c-c++> .\qstn
x = 13
as you will notice this code work as spected. But happens here in detail?
First read What's the difference between passing by reference vs. passing by value?
Now that you're done reading, let's try a slightly more complicated example so we can really see the difference:
int main(){
a A;
A.set(13.0).set(42).print();
A.print();
return 0;
}
If we return by reference A will be modified by set(13.0) and then A is returned and modified again by set(42). Output will be
x = 42
x = 42
but if we return by value A will be modified by set(13.0) and then a new temporary a that is a copy of A will be returned. This copy is modified by set(42), not A.
Output will be
x = 42
x = 13
We have failed to cascade.

'this' pointer behaviour in c++

I have a basic understanding of this pointer in C++.While studying have come across the following code:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
My issue is why the compiler deosn't report an error where I am returning a this pointer in SetX and SetY functions but haven't stated the return type as a pointer?
This comes because you're returning *this not this.
this is the pointer to a object of type Test. This means the this-variable basically holds the address where the object is stored. To access the object on which this points you use the *.
So you're returning the actual object on which you this Pointer points at.
EDIT
The problem why your code does not work in the way you want it to do is caused by the fact, that you're working on the stack.
Let's take a look at the addresses:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) {
y = b;
cout << this << endl; // >> 0x29ff18
return *this;
}
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
cout << &obj1 << endl; // >> 0x29ff10
obj1 = obj1.setX(10).setY(20);
cout << &obj1 << endl; // >> 0x29ff10
//obj1.setY(20);
obj1.print();
return 0;
}
As you can see, the object where this points at is at a different address within you setY method compared to the main. This is because the object is copied to the stackframe of the setY method - so within setX and setY you're working with a copy of obj1
If you're doing obj1.setX(10).setY(20); you basically copy the object obj1 and use it within setX and the return object of setX is then used in setY. If you want to save the last copy, you have to reassign it to obj1.
Your solution to the problem works, but is grossly inefficient. The last paragraph describing what is happening is incorrect. setx is called with and uses obj1. sety is called with and uses copy of obj1. obj1 is then assigned copy of copy of obj1 returned by sety. The address doesn't change because obj1's storage is being overwritten, not replaced. Add a copy constructor and an assignment operator and you can watch what's really happening. The recommended solution is to use references to the same object throughout and chaining as per #πάνταῥεῖ 's answer below. – user4581301
My issue is why the compiler deosn't report an error where I am returning a this pointer in SetX and SetY functions but haven't stated the return type as a pointer?
It's completely valid syntax, so the compiler isn't supposed to return an error message. The problem is that you're using copies of this* with your return type.
To chain operations properly to operate on the original instance return a reference to this:
Test& setX(int a) { x = a; return *this; }
// ^
Test& setY(int b) { y = b; return *this; }
// ^
Otherwise you're returning an unrelated copy of your class.

What's the difference between function that returns float and float&?

What's the difference in usage of function get1() and get2()?
struct x
{
float get1() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
float& get2() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
};
int main()
{
x t;
float x1 = t.get1();
float/*&*/ x2 = t.get2();
cout << x1 << endl;
cout << x2 << endl;
cin.get();
}
As i understand, get2() can only be const class member..
It's not clear for me completely. If someone can point me to a reference or just a short but complete solution, would be nice.
In your case, get2() invokes undefined behavior because you return a reference to a method-local that goes out of scope.
The difference is that returning float returns a float value, while float & returns a reference to a float. The reference can be used to alter the data of the referent; when returning by value you just get a copy.
It sounds like you are just confused about what references do, so here is the colloquial definition: a reference is another name for an object. That means that a reference requires the existence of its target to exist elsewhere, very similar to a (non-null) pointer.
Let me write a better example to illustrate the difference:
struct x
{
x() : data(0) { }
float get1() const
{
return data;
}
// Cannot be const now, because we can't return a non-const reference to what
// would be a const data member. (If this method were const then data would be a
// const float, and that cannot bind to float &.)
float & get2()
{
return data;
}
private:
float data;
};
Now we have two methods, one that returns data and one that returns a reference to it. The difference here is that with get2() you can actually change the value of x::data:
x an_x;
float a = an_x.get1(); // a is 0
a = 5; // a is 5, an_x.data is still 0
a = x.get1(); // a is 0 again, because an_x.data did not change
float & b = an_x.get2(); // b is 0
b = 5; // b is 5, and so is an_x.data!
a = x.get1(); // a is now 5, because an_x.data is 5
Notably, returning a reference makes the result of the expression an lvalue:
an_x.get1() = 5; // Compile-time error, because a float is not an lvalue.
an_x.get2() = 5; // Compiles, and sets an_x.data to 5.
This is a technique used by the standard library containers; vector<int> for example returns int & from its non-const operator[] overload, which is why some_vector[0] = 5; compiles and works as you would expect.
float fx = 4;
In your case fx is local variable. It will die once you come out of function. If you are returning float then you are making copy of value, so even fx die, no problem. But if you are returning float&, you are returning reference to died variable. Which is undefined behaviour.
Copying is costly operation. When you return reference, you are not making actual copy, but you are returning address of varaiable. You should return reference if your variable will alive after returning from function. But in your case, fx will die once you come out of function.
I simulated your case in below blocks of code, you can compare the output of two case for making clearly. Hope it help.
#include <iostream>
class A
{
public:
A()
{
std::cout << this << ": A()\n";
}
A(const A&)
{
std::cout << this << ": Copy constructor\n";
}
~A()
{
std::cout << this << ": ~A()\n";
}
};
struct x
{
A get1() const
{
A a;
return a;
}
A &get2() const
{
A a;
return a;
}
};
int main(int argc, char *argv[])
{
x t;
/*{
t.get1();
}*/
{
t.get2();
}
std::cin.get();
}

Codepad.org C++ code gives wrong result

Just a tiny question:
Can you tell me what's the issue here in this code ? It should print out 9 but it does 4.8921e-270, however, when uncommenting line 4, it works just fine, too.
I don't understand what might be wrong here. Thank you !
Code:
double& foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
int main() {
cout << foo() << "\n";
}
Result:
4.8921e-270
It is a bad idea to return references/pointers to objects on the stack. They are likely destroyed when you leave the function. Try returning it as per value:
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Now the return value is copied instead of a reference to an object that is probably not existing anymore.
You are returning a reference to a local object, the object ceases to exist when foo completes, and then you get Undefined Behavior when you dereference it.
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Never a good idea to return references to objects on stack. Most likely they would be disappear when you leave the function. You might try returning it as per value.
You return a reference to a local variable - since the local variable goes out of scope as soon as foo() returns, the value no longer exists.
So you should either just change the return type to double (highly recommended) and return x or (if you absolutely want/have to return a reference) use a static variable instead:
double& foo() {
static double x = 9;
double &y = x;
return y;
}
I often return data members of a class by const ref:
class BigThing {...};
class Foo
{
public:
const BigThing & getBT() const { return bt; } // For constant BigThing.
BigThing & getBT() { return bt; } // For mutable BigThing.
private:
BigThing bt;
};
Then as long as your instance of Foo is in scope (you don't want to return a ref to a local variable) then using one of the getBT() should be safe and efficient.

Question with virtual functions

I have two classes:
class x {
public:
virtual void hello() {
std::cout << "x" << std::endl;
}
};
class y : public x {
public:
void hello() {
std::cout << "y" << std::endl;
}
};
Can someone explain why the following two calls to hello() print different messages? Why don't they both print "y"? Is it because the first one is a copy while the second one actually points to the object in memory?
int main() {
y a;
x b = a;
b.hello(); // prints x
x* c = &a;
c->hello(); // prints y
return 0;
}
Yes, you are right
x b = a;
Invokes a copy constructor (b IS an 'x')
x& b = a;
Assigns a reference and will use the override (b is still actually a 'y')
Because x b = a; slices the object.
When this code executes, it creates a new x, not a y, which is a copy of the original y, a'.
x b = a copies a to b. Since b is type x, you end up with an object of type x. An object of type x will print x.
The only way you get y is when you are calling into an object of type y.
b.hello() prints "x" because b is an instance of class X. c->hello() prints "y" because c points to a, and a is an instance of class Y.
What might be confusing for you is that when you write x b = a;, you're creating a new object b and initializing it with a. When you write x* c = &a;, c is not a new object. You just introduced an alias to an existing object.