#include "stdafx.h"
#include "iostream"
using namespace std;
class complex
{
int real;
int img;
public:
complex(int x = 0, int y = 0)
{
cout << "Inside Prama" << endl;
real = x;
img = y;
}
complex operator+(complex x)
{
complex temp;
temp.real=real + x.real;
temp.img=img + x.img;
return temp;
}
void display()
{
cout << real << ' ' << img << endl;
}
};
int main()
{
class complex c1(5,6), c2(7,8),c3(7,7),c4;
c1.display();
c2.display();
c3.display();
c4 = c1+c2+c3;
c4.display();
return 0;
}
for above operator overloading code following is the output:
why that parameterized constructor is called at the time of adding of the objects.I am not getting the reason for that
Just summarizing comments...
Here
complex operator+(complex x)
{
complex temp;
temp.real=real + x.real;
temp.img=img + x.img;
return temp;
}
complex temp; calls the constructor and thats the output you see. Typically you'd pass x as const reference to avoid the copy, but as you need a copy anyhow you can use x:
complex operator+(complex x)
{
x.real +=real;
x.img +=img;
return x;
}
This will only invoke the compiler generated copy constructor when you call the operator.
There are more subtleties to consider. Using x instead of making a local copy inhibits named return value optimization. Also it is common to implement operator+ in terms of operator+= and operator+ can be a free function then. Note that operator+= can be more efficient, because no copy is needed at all. For more details on operator overloading in general I refer you to What are the basic rules and idioms for operator overloading?
PS: "parametrized constructor" is a term I have seen only in poor misleading tutorials so far. It is not an official term. The relevant term here is default constructor. complex(int x = 0, int y = 0) is a default constructor because it can be called without parameters. It is a good example for why "parametrized constructor" does not convey lots of meaning and is rather misleading.
Related
The code below shows a class representing complex numbers. My interest is in understanding the operator+ function. As I understand Complex res should be allocated on the frame of the function operator+. Is it correct to return this object to the caller? By the time this function returns the frame would have been popped but res would continue to be used by the caller. Unless there is more to this than meets the eye, like the actual return res may actually be copying the object from current frame to the caller's frame. Another possibility can be that the code inside the operator+ function may be inlined on the call site in main? From my limited understanding of the language, functions declared within the class are by default inlined on the call site. Any help will be appreciated.
#include<iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
Complex operator+(Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
PORTION BELOW ADDED TO CLARIFY THE SOLUTION AFTER READING THE COMMENTS AND ANSWERS BELOW
I updated the code above with the following:
#include<iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
Complex operator+(Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
cout << "Address inside the function " << &res << "\n";
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
cout << "Address outside the function " << &c3 << "\n";
c3.print();
}
The output shows two different addresses on two different regions of the stack indicating copy by value during return:
Address inside the function 0x7fffbc955610
Address outside the function 0x7fffbc955650
Is it correct to return this object to the caller?
C++ supports both return by reference and return by value. Since you are not using return by reference, you are not returning a reference to the object to the caller. You are using return by value, so you are returning the object's value to the caller. Consider:
int foo()
{
int i = 2;
return i;
}
This returns the value 2. It does not return the object i. That i itself no longer exists after the return doesn't matter because its value has already been used to determine the value returned.
Transfer with value always uses stack.
When you want to return a value, depending on the caller code, the copy constructor or assignment operator may implicitly call and assign the return value to the object on the left. (lvalue)
Complex nwobj=cmpx1 + cmplx2; //copy constructor used to assign return object to lvalue
cmplx3=cmplx1+xmplx2;//operator= used to make a right assignment.
Note:
The copy construction in the first line may happen or may be elided depending on the used compiler and its settings. A comprehensive explanation about this can be found in:
SO: What are copy elision and return value optimization?
I'm trying to understand how the copy assignment constructor works in c++. I've only worked with java so i'm really out of my waters here. I've read and seen that it's a good practice to return a reference but i don't get how i should do that. I wrote this small program to test the concept:
main.cpp:
#include <iostream>
#include "test.h"
using namespace std;
int main() {
Test t1,t2;
t1.setAge(10);
t1.setId('a');
t2.setAge(20);
t2.setId('b');
cout << "T2 (before) : " << t2.getAge() << t2.getID() << "\n";
t2 = t1; // calls assignment operator, same as t2.operator=(t1)
cout << "T2 (assignment operator called) : " << t2.getAge() << t2.getID() << "\n";
Test t3 = t1; // copy constr, same as Test t3(t1)
cout << "T3 (copy constructor using T1) : " << t3.getAge() << t3.getID() << "\n";
return 1;
}
test.h:
class Test {
int age;
char id;
public:
Test(){};
Test(const Test& t); // copy
Test& operator=(const Test& obj); // copy assign
~Test();
void setAge(int a);
void setId(char i);
int getAge() const {return age;};
char getID() const {return id;};
};
test.cpp:
#include "test.h"
void Test::setAge(int a) {
age = a;
}
void Test::setId(char i) {
id = i;
}
Test::Test(const Test& t) {
age = t.getAge();
id = t.getID();
}
Test& Test::operator=(const Test& t) {
}
Test::~Test() {};
I can't seem to understand what i should be putting inside operator=(). I've seen people returning *this but that from what i read is just a reference to the object itself (on the left of the =), right? I then thought about returning a copy of the const Test& t object but then there would be no point to using this constructor right? What do i return and why?
I've read and seen that it's a good practice to return a reference but i don't get how i should do that.
How
Add
return *this;
as the last line in the function.
Test& Test::operator=(const Test& t) {
...
return *this;
}
Why
As to the question of why you should return *this, the answer is that it is idiomatic.
For fundamental types, you can use things like:
int i;
i = 10;
i = someFunction();
You can use them in a chain operation.
int j = i = someFunction();
You can use them in a conditional.
if ( (i = someFunction()) != 0 ) { /* Do something */ }
You can use them in a function call.
foo((i = someFunction());
They work because i = ... evaluates to a reference to i. It's idiomatic to keep that semantic even for user defined types. You should be able to use:
Test a;
Test b;
b = a = someFunctionThatReturnsTest();
if ( (a = omeFunctionThatReturnsTest()).getAge() > 20 ) { /* Do something */ }
But Then
More importantly, you should avoid writing a destructor, a copy constructor, and a copy assignment operator for the posted class. The compiler created implementations will be sufficient for Test.
We return a reference from the assignment operator so we can do some cool tricks like #SomeWittyUsername shows.
The object we want to return a reference to is the one who the operator is being called on, or this. So--like you've heard--you'll want to return *this.
So your assignment operator will probably look like:
Test& Test::operator=(const Test& t) {
age = t.getAge();
id = t.getID();
return *this;
}
You may note that this looks strikingly similar to your copy-constructor. In more complicated classes, the assignment operator will do all the work of the copy-constructor, but in addition it'll have to safely remove any values the class was already storing.
Since this is a pretty simple class, we have nothing we need to safely remove. We can just re-assign both of the members. So this will be almost exactly the same as the copy-constructor.
Which means that we can actually simplify your constructor to just use the operator!
Test::Test(const Test& t) {
*this = t;
}
Again, while this works for your simple class, in production code with more complicated classes, we'll usually want to use initialization lists for our constructors (read here for more):
Test::Test(const Test& t) : age(t.getAge()), id(t.getId()) { }
Returning reference to the original object is needed for support of nested operations.
Consider
a = b = c
I would like to know if copying an object in the following manner is acceptable vis-a-vis copying the individual elements.
#include <iostream>
using namespace std;
class abc{
public:
abc(int a = 10, int b = 5);
abc(const abc &obj, int b = 10);
int ret_x() { return x; }
int ret_y() { return y; }
private:
int x;
int y;
};
abc::abc(int a, int b)
: x(a),
y(b)
{
}
abc::abc(const abc &obj, int b)
{
if (this != &obj) {
*this = obj; -----> Copying the object
}
y = b;
}
int main()
{
abc a1;
cout << "A1 values: " << a1.ret_x() << "\t" << a1.ret_y() << endl;
abc a2(a1, 20);
cout << "A2 values: " << a2.ret_x() << "\t" << a2.ret_y() << endl;
return 0;
}
Edit:
Use case:
The issue is that object a1 is auto-generated and hence any newly introduced members in the class could not be updated. I could provide a member function to update the new members, sure, but wanted to explore this option.
The code works fine, but is the method correct?
Thanks!
As chris noted already in the comments, you are creating a completely new object. How would you want to get this passed into the constructor? Well, actually, you could perhaps via placement new:
abc a;
abc* b = new(&a)abc(a);
But this is a such an exotic case that I would not consider it, I even dare to claim someone using advanced stuff such as placement new should know what he is doing... So leave out the if-check.
In your special case, it seems OK, as no data exists that might require deep copying. Be aware, though, that you are assigning the member b twice. Not really critical with int, but on larger objects (std::string, std::vector, ...) which do deep copies this gets more and more questionable.
With C++11, though, I would prefer constructor delegation:
abc::abc(const abc& obj, int b)
: abc(obj) // copying here
{
y = b;
}
This does not solve, however, the double assignment problem. To be honest, this might not always be a true problem, in many cases the compiler might optimise the first assignment away (especially in the int case of our example). But on more complex data types (possibly already std::string), I wouldn't feel comfortable relying on the compiler detecting obsolete assignment...
Be aware that you might get into trouble if you have resources managed internally:
struct abc
{
int* array;
abc() : array(new int[7]) { }
~abc()
{
delete[] array;
}
}
Not providing an appropriate assignment operator or copy constructor – depending on the implementation variant, yours (assignment) or mine (constructor delegation) – doing the necessary deep copy will result in multiple deletion of the same data (undefined behaviour!). Following the rule of three (or more recently, rule of five), you most probably will need both anyway. You might consider the copy and swap idiom idiom then.
Finally a trick to avoid double assignment:
abc(abc const& other)
: abc(other, other.y)
{ }
abc(abc const& other, int y)
: x(other.x), y(y)
{ }
Question is about multiple constructors that confuses me.
#include "complex.h"
#include <iostream>
using namespace std;
Complex::Complex(double realPart, double imPart)
: m_R(realPart), m_I(imPart)
{
cout << "complex(" << m_R << "," << m_I << ")" << endl;
}
Complex::Complex(double realPart)
{
Complex(realPart, 0);
}
Complex::Complex() : m_R(0.0), m_I(0.0)
{
}
int main() {
Complex C1;
Complex C2(3.14);
Complex C3(6.2, 10.23);
}
Can someone explain how compiler knows which constructor to use of three defined? Primer is from this book, page 58.
Side Note
If you want to utilize C++ 11 delegating constructors you should write:
Complex::Complex(double realPart)
: Complex(realPart, 0)
{}
instead of
Complex::Complex(double realPart) {
Complex(realPart, 0);
}
which creates a temporary unused Complex inside the constructor body.
It depends on the number and types of arguments supplied to the constructor. Thus
std::Complex first(1, 2.0); // Use first constructor
std::Complex second(5.0); // Use second constructor
std::Complex third; // Use third constructor with no arguments.
I want to have double values with a name and units, but I want to use them as if they were simple doubles. For example I want to use them like this:
int main(){
NamedValue a("a","m");
NamedValue b("b","m");
NamedValue c("c","m^2");
a = 3;
b = 5;
c = a*b;
std::cout << a << b << c << std::endl;
return 0;
}
and the output should be:
a = 3 m
b = 5 m
c = 15 m^2
I came up with this solution:
class NamedValue {
public:
NamedValue(std::string n,std::string u) : name(n),units(u){}
const std::string name;
const std::string units;
void operator=(double v){this->value = v;}
void operator=(const NamedValue& v){this->value = v.value;}
operator double() const { return value; }
private:
double value;
};
std::ostream& operator<<(std::ostream& stream,const NamedValue& v) {
stream << v.name << " = " << (double)v << " " << v.units << std::endl;
return stream;
}
Unitl now it works nicely, but I am mainly concerned about the assignment operator void operator=(const NamedValue& v){this->value = v.value;} that is not exactly doing, what one normally would expect of an assignment operator.
Are there any bad consequences that I will face?
I am thinking about things like passing an object as parameter and stuff like that. However, a function like this
NamedValue test(NamedValue x){return x;}
works without problems, as there is no assignment involved (only copy constructor). Am I missing something? Is there anything else I should be aware of?
ps: Just in case you wonder, at the moment I do not care about checking the units when doing calculations.
The assignment operator is totally fine. The only thing unusual about it is that you did not return the object so the operator calls cannot be chained. Otherwise, it's a completely normal operator.