I am new to C++ and as a practice I made a fraction class "Frac". Everything seems to work fine except when I want to print the result of operations like (a+b), a and b being Frac objects. In my main function, I use:
Frac a(5, 2), b(9, 2), c(a+b); //Three fractions a=5/2, b=9/2, and c = a+b = 14/2 = 7/1
cout << (a+b) << endl; //This line's result makes no sense to me : always 2686600/4201035
cout << c << endl; //This line's result is ok : 7/1
Here is how I overloaded operator<< :
ostream& operator<<(ostream &stream, Fract const& a){
stream << a.getNum() << "/" << a.getDenom(); //Num is numerator of fraction a, Denom is its denominator
return stream;
}
operator+ :
Fract& operator+(Fract const& a, Fract const& b){
Fract copy(a);
copie += b;
return copy;
}
operator+= :
Fract& Fract::operator+=(Fract const& b){
Fract copy(b);
//Put on same denominator for add
copy.m_denom *= m_denom;
copy.m_num *= m_denom;
m_denom *= b.m_denom;
m_num *= b.m_denom;
//Now on same denominator
m_num += copy.m_num;
Fract::simplify();
return *this;
}
The getters :
int Fract::getDenom() const{return m_denom;}
int Fract::getNum() const{return m_num;}
When I debug the program, everything is fine until this line in operator<< :
stream << a.getNum() << "/" << a.getDenom();
Before its execution, the values of a.m_num and a.m_denom are good (7 and 1, checked with debugger), but after the first call (a.getDenom() here), a.m_num and a.m_denom switch from 7 and 1 to 2686600 and 4201035! It is the same thing no matter the operator, so ...
Fract a(5,2), b(9,2);
cout << (a+b) << endl << (a*b) << endl << (a/b) << endl << (a-b);
... 's output is :
2686600/4201035
2686600/4201035
2686600/4201035
2686600/4201035
and ...
Fract a(5,2), b(9,2), c(a+b), d(a*b), e(a/b), f(a-b);
cout << c << endl << d << endl << e << endl << f;
... 's output is :
7/1
45/4
5/9
-2/1
All correct results...
This drove me crazy. I searched for hours but did not find the solution or someone who had the same problem. It would be realy nice if someone could help me.
Thank you guys.
Fract& operator+(Fract const& a, Fract const& b){
Fract copy(a);
...
return copy;
}
You're returning a reference to a local variable but when that variable expires all the data is gone. You should be returning by value:
Frac operator+(...)
Related
Consider this code:
# include <iostream>
using namespace std;
int main()
{
for(int i = 5; i>0;)
{
i--;
cout <<i<<" ";
}
return 0;
}
The output of this code would be 4 3 2 1 0.
Can I change the decrement/increment value?
In detail, this means that the default decrement/increment value is 1. So you either minus 1 or add 1.
Can I change it to minus 0.2 or add 1.3?
If so, is there a way to tell the compiler that I want to change the -- value from 1 to 0.2 and still using the -- operator instead of changing it to -= 0.2?
d-- is shorthand for d -= 1, which is shorthand for d = d - 1.
You should not read this as a mathematical equation, but as "calculate d - 1 and assign the result as the new value of d".
#include <iostream>
int main()
{
float day = 1.2;
for(int i = 0; i < 5; i++)
{
day -= 0.2;
std::cout << day;
}
return 0;
}
(I also removed using namespace std as it is bad practice).
Note the second part of the for loop is a condition that keeps the loop going as long as it is true. In your case, i > 5 is false from the beginning (because 0 < 5) so the loop will never run. I assumed you meant i < 5 instead.
i-- is the post-fix decrement operator. For builtin types it means that i is decremented by one (1). The value of the expression i-- is the value of i before decrementing it.
--i is the pre-fix decrement operator. For builtin types it means that i is decremented by one (1). The value of the expression --i is the value of i after decrementing it.
For the builtin types you cannot change the behaviour of the increment or decrement operators. If you want to have another behaviour, you need to fallback to the operators += and -= where you can add whatever you want. But please note that your code used int and you probably want to change to float or double first before adding or subtracting 0.1 or 0.2.
You can change the behaviour for increment and decrement operators for your own types, though. Here is an exammple
#include <iostream>
struct S {
S& operator++() { // prefix increment "++s"
d += increment_value;
return *this;
}
S& operator--() { // prefix decrement "--s"
d -= decrement_value;
return *this;
}
S operator++(int) { // postfix increment "s++"
S copy{*this};
d += increment_value;
return copy;
}
S operator--(int) { // postfix decrement "s--"
S copy{*this};
d -= decrement_value;
return copy;
}
double d{};
double increment_value{0.2};
double decrement_value{0.1};
friend std::ostream& operator<<(std::ostream& os, const S& s) {
os << s.d;
return os;
}
};
int main(int, char**) {
S s{1};
std::cout << "val=" << s.d << '\n';
std::cout << "prefix++=" << ++s << '\n';
;
std::cout << "val=" << s.d << '\n';
std::cout << "postfix++=" << s++ << '\n';
std::cout << "val=" << s.d << '\n';
std::cout << "prefix--=" << --s << '\n';
std::cout << "val=" << s.d << '\n';
std::cout << "postfix--=" << s-- << '\n';
std::cout << "val=" << s.d << '\n';
}
The output is
val=1
prefix++=1.2
val=1.2
postfix++=1.2
val=1.4
prefix--=1.3
val=1.3
postfix--=1.3
val=1.2
You might notice that I added two operator ++ and two operator--. One of each is getting no parameter, the other is getting an int. As cppreference describes, the int parameter is only a dummy parameter to differentiate between the prefix and the postfix versions of the operators. (*)
As you can also see, the prefix operators are more performant as they don't need the extra copy. So normally please use the prefix versions (compare the CppCoreGuidelines).
But, please ignore the possibility to change the increment and decrement operators. It is counter intuitive and only a source of errors and head aches. Don't do it this way!
(*) This parameter could also be used for even more confusing behaviour, but it should be clear that this is making the idea even worse. So see this just as an example of what is technically possible.
#include <iostream>
struct S {
S operator++(int diff) { // postfix increment "s++", diff defaults to zero (0)
S copy{*this};
d += diff ? diff : increment_value;
return copy;
}
S operator--(int diff) { // postfix decrement "s--", diff defaults to zero (0)
S copy{*this};
d -= diff ? diff : decrement_value;
return copy;
}
double d{};
double increment_value{0.2};
double decrement_value{0.1};
friend std::ostream& operator<<(std::ostream& os, const S& s) {
os << s.d;
return os;
}
};
int main(int, char**) {
S s{1};
std::cout << "val=" << s.d << '\n';
s++;
std::cout << "val=" << s.d << '\n';
s.operator++(2);
std::cout << "val=" << s.d << '\n';
s--;
std::cout << "val=" << s.d << '\n';
s.operator--(2);
std::cout << "val=" << s.d << '\n';
}
results in
val=1
val=1.2
val=3.2
val=3.1
val=1.1
You can change the loop variable both inside the for and the body any way you like. For example:
for (double d = 4; d > 0; d = cos(d) + 1 / d) {
d = sin(d);
std::cout << d << " ";
}
C++ does not have a fixed count loop like other languages for i = 0 to 10 do ... done where the i can not be changed. Do whatever you like.
Note: I change the type to double since you asked about decrementing by 0.2. The type int doesn't allow that.
Can I change the decrement/increment value?
Yes, that is what the third parameter(?) in the for loop does.
#include <iostream>
int main()
{
for(int i = 5; i > 0; i -= 2)
{
std::cout << i << std::endl;
}
return 0;
}
Can I change it to minus 0.2 or add 1.3?
Yes, you'd simply change the first parameter to be a float and the third parameter to decrement/increment by whatever you'd like.
#include <iostream>
int main()
{
for (float i = 5; i > 0; i -= .2)
{
std::cout << i << std::endl;
}
return 0;
}
If I understand correctly what you want to do is to change the behavior of T operator --();.
You can do that with your own type:
struct Foo {
float boat;
auto operator --() noexcept { return boat -= .2f; }
operator float() const noexcept { return boat; }
};
#include <cstdio>
int main() {
for (Foo i{ 5 }; i > 0; --i) {
std::printf("%1.2f, ", static_cast<float> (i));
}
}
Live on Compiler Explorer
Should you ever do that? No, you shouldn't. But now you know how not to do it should the opportunity not come.
As a general opening question, it can be stated as why some times destructor gets called in the middle of the code?!
what are the different possible scenarios can call a destructor.?
I would like to understand the similar effect in the following code
class complex
{
private:
double re, im;
protected:
public:
complex()
{
cout << "def const " << endl;
}
complex(double r, double i)
{
cout << "parameterized " << endl;
re = r;
im = i;
}
void setdata(double r, double i)
{
re = r;
im = i;
}
void getdata()
{
cout << "enter real" << endl;
cin >> re;
cout << "enter im" << endl;
cin >> im;
}
//there are 3(?) possible variants of addition...check
//1st
void add(complex c1, complex c2)
{
cout << "in add" << endl;
re = c1.re + c2.re;
im = c1.im + c2.im;
}
//2nd
void add(complex c)
{
cout << "in add" << endl;
re += c.re;
im += c.im;
}
//3rd --- (???)
// complex add(complex c1, complex c2)
// {
// complex retc;
// retc.re = c1.re + c2.re;
// retc.im = c1.im + c2.im;
//
// return retc; //this one is very weird
// }
void display()
{
cout << endl << re << " + " << im << "i" << endl;
}
void mul(complex c1, complex c2)
{
cout << "in mul" << endl;
re = c1.re*c2.re - c1.im*c2.im;
im = c1.re*c2.im + c1.re*c2.im;
}
complex mul(complex c)
{
cout << "in mul" << endl;
complex retc;
retc.re = re*c.re - im*c.im;
retc.im = re*c.im + c.re*im;
return retc;
}
~complex()
{
cout << re << " + " << im << "i" << endl;
cout << "dest" << endl;
}
};
int main()
{
complex c1;
c1.getdata();
complex c2(5, 5);
complex c3;
c3.add(c1, c2); //to store the answer of c1 + c2 we need c3 object
c3.display();
//perform c1 + c2 * c3
complex c4;
c4.add(c1, c2.mul(c3)); //can not use mul(c2, c3) for c2 * c3...why???!
cout << "ans1" << endl;
c4.display();
//or we can also do...
c1.add(c2.mul(c3)); //but this will modify c1
cout << "ans2" << endl;
c1.display();
return 0;
}
following is the output
def const
enter real
1
enter im
2
parameterized
def const
in add
1 + 2i
dest
5 + 5i
dest
6 + 7i
def const
in mul
def const
in add
1 + 2i
dest
-5 + 65i
dest
6 + 7i
dest
ans1
-4 + 67i
in mul
def const
in add
-5 + 65i
dest
6 + 7i
dest
ans2
-4 + 67i
-4 + 67i
dest
6 + 7i
dest
5 + 5i
dest
-4 + 67i
dest
any idea why do destructors get called in the middle of nowhere!?
why some times destructor gets called in the middle of the code?
Take these methods for illustration:
void mul(complex c1, complex c2)
{
cout << "in mul" << endl;
re = c1.re*c2.re - c1.im*c2.im;
im = c1.re*c2.im + c1.re*c2.im;
}
void add(complex c1, complex c2)
{
cout << "in add" << endl;
re = c1.re + c2.re;
im = c1.im + c2.im;
}
You invoke it with:
c4.add(c1, c2.mul(c3));
Both add() and mul() are receiving their parameters by value. When the compiler sees a pass-by-value parameter, it creates a new version of the parameter object by means of the copy constructor. All classes have a default copy constructor, which assigns each field member one by one. This new version is used throughout the method, and finally destroyed.
So, when you call mul() in c2 with c3 as parameter, a new complex object is created from c3, and when the end of mul() is reached, it is destroyed. The same happens with the call to add() with c1 and the result of c2.mul(c3).
If you want to avoid this copying (which takes time and resources), then you should change the kind of parameter passing in your functions. Specifically, you can pass them by pointer or by reference. The problem is that this would allow modifications of them inside the function: but in the concrete case of pass-by-reference, you can modify it with const, which gets you the best of both worlds: you get the object efficiently passed without the possibility of modification.
void mul(const complex &c1, const complex &c2)
{
cout << "in mul" << endl;
re = c1.re*c2.re - c1.im*c2.im;
im = c1.re*c2.im + c1.re*c2.im;
}
void add(const complex &c1, const complex &c2)
{
cout << "in add" << endl;
re = c1.re + c2.re;
im = c1.im + c2.im;
}
Taking into account that the methods above do not modify the instance they are being called against, they can be also const themselves.
void mul(const complex &c1, const complex &c2) const
{
cout << "in mul" << endl;
re = c1.re*c2.re - c1.im*c2.im;
im = c1.re*c2.im + c1.re*c2.im;
}
void add(const complex &c1, const complex &c2) const
{
cout << "in add" << endl;
re = c1.re + c2.re;
im = c1.im + c2.im;
}
Also, since these functions do not require an instance of complex, they could also be independent, friend functions, or static methods. Actually, that is worth another answer.
Just as a rule of thumb, when you have just one argument of the same class, as in void mul(complex c2), that's probably a member of the class; you're going to invoke it as c1.mul( c2 ). When you have two arguments, as in void mul(complex c1, complex c2) then it is an independent function (i.e., you'll invoke it as mul( c1, c2 ), that it can be friend if you want it wrapped inside your class or access to the private member of your class. Normally you create these friend functions because you have an operator with an object of another class (or a primitive) at its left. Another issue is that an independent function should better return a new object instead of modifying one of its arguments... as you can see, it gets more and more complex.
Anyway, these are the signatures your methods should sport:
class complex {
public:
// ... more things...
void mul(complex c2);
complex operator*(const complex &c2);
friend complex operator*(int x, const complex &c1);
// ... more things...
};
Also, instead of tying your class to the console with the display() function, better overload the operator <<, and you'll be able to use that functionality with any stream.
Find the complete code in IDEOne.
Hope this helps.
Destructors are called when you delete a pointer explicitly, at the end of the scope for scope variables and at the end of the statement for temporaries.
In your case in
c4.add(c1, c2.mul(c3));
you need to compute c2.mul(c3). It will create a new complex class instance. It will be kept around for add to execute, and it will be destroyed when the call is done, since it's no longer needed.
First of all keep in mind that you should only concern about calling a destructor for an object created dynamically in run time. One straight forward answer for this is, YOU need to verify your codes carefully and find out all the dynamically created objects in your codes and check exactly when it is going to out of scope i.e. the time/area from when that object is never going to use any more, and exactly that point of time you need to call the destructor of that object to clear heap memory. Please keep in mind that destructor is for releasing/cleaning memory to avoid memory leak and better memory management in a process.
This question already has answers here:
Returning a reference to a local variable in C++
(3 answers)
Closed 6 years ago.
I'm trying to build a class complex,
and in the method conjugate I want the return statement to return the same object as the local variable res and not a copy of it.
#include <iostream>
#include <math.h>
using namespace std;
class complex
{
float x, y;
public:
complex(float x, float y);
complex(float x) :complex(x, 0){}
complex() :complex(0, 0){}
complex(const complex &z) : complex(z.x, z.y) {}
~complex();
complex &conjugate();
friend ostream& operator<<(ostream&, const complex&);
};
ostream& operator<<(ostream& out, const complex& z){
out << z.x << "+" << z.y << "i";
return out;
}
complex::complex(float x, float y){
cout << "complex number created.\n";
this->x = x;
this->y = y;
}
complex &complex::conjugate(){
complex res;
res.x = this->x;
res.y = -this->y;
cout << "res val: " << res << endl;
cout << "res addr: " << &res << endl;
return res;
}
int main(){
complex a(1, 2);
complex* c = &(a.conjugate());
cout << "c val= " << *c << endl;
cout << "c addr= " << c << endl;
getchar();
return 0;
}
Output:
complex number created.
complex number created.
res val: 1+-2i
res addr: 002CFA0C
c val: -1.07374e+008+-1.07374e+008i
c addr: 002CFA0C
*c and the local variable res have the same address but not the same value.
Could anyone explain to me why?
res disappears after conjugate returns. You made what is called a dangling reference/pointer which is an error in the program. After you call conjugate again it makes a new variable res that happens to have the same address, but not the same value.
To solve this issue you can make res a static variable (static complex res;) so its lifetime persists past the end of the function.
You are returning a reference to a local variable that is about to be destroyed at the end of the function scope. That will not end well. Basically, the reference is useless since it refers to a destroyed object and using it is undefined - anything could happen, the code is broken.
As I specified in the title, this is a problem that puzzled me enormously, and still I can not find a fix for it.
I created a Point class which has three private attributes (_id, _x and _y) with related public get and set methods.
For example, I created three points (G, H, R), where the point G is a "parent". Point H is the prototype of the point G (a clone) and point R will be the outcome of the meeting points (G+H) (addition of the points).
Points sample:
Point G ("pG", 3.5f, 6.5f);
Point H (G.prototype ()); H.setId ("pH");
Point R;
R = G + H;
The program works correctly, but unfortunately after the operation {R=G+H}, _id attribute of point G becomes the clone attribute of point R, I do not understand why this is happening because the evaluation is done from right to left (H+, +G, =R).
The question is why G point attribute changes itself?
Code where the problem occurs:
#include <iostream>
#include <string>
using namespace std;
class Point
{
private:
string _id;
double _x;
double _y;
public:
Point(string id="undefined", double x = 0.00f, double y = 0.00f)
:_id(id), _x(x), _y(y){}
~Point(){}
public:
// Getters methods
string getId() const { return _id;}
double getX() const { return _x; }
double getY() const { return _y; }
void setId(string id) { _id = id; }
// Setters methods
void setX(double n = 0.00f) { _x = n; }
void setY(double n = 0.00f) { _y = n; }
Point prototype() { return Point(_id, _x, _y); }
Point operator+ (const Point& p)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id),
_x+p._x,
_y+p._y
);
}
Point operator= (const Point& p)
{
cout << "Operator = called, returning a new object Point(p._id, p._x, p._y)" << endl;
_id=p._id;
_x=p._x;
_y=p._y;
return *this;
}
};
int main()
{
Point G("G",10.0f, 10.0f);
Point H(G.prototype()); H.setId("H");
Point R;
R = G + H;
cout << "object Point {id: " << G.getId() << ", x: " << G.getX() << ", y: " << G.getY() << "}" << endl;
cout << "object Point {id: " << H.getId() << ", x: " << H.getX() << ", y: " << H.getY() << "}" << endl;
cout << "object Point {id: " << R.getId() << ", x: " << R.getX() << ", y: " << R.getY() << "}" << endl;
return 0;
}
Thanks in advance!
Point operator+ (const Point& p)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id), // HERE
_x+p._x,
_y+p._y
);
}
In this line, you modify _id property of this object. As a rule of thumb, binary + operator should be a const member or - IMO cleaner - a static method taking two const reference arguments.
BTW, you can add strings in C++ by just applying + operator to them (_id + "+" + p._id).
If you implement your binary arithmetic operators as members, you should consider making the operator a const member. This would catch the obvious modification in your implementation (the implementation is made out of line to avoid including unrelated code):
Point Point::operator+ (const Point& p) const
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id),
_x+p._x,
_y+p._y
);
}
The operation _id.append("+") actually operates on this->_id, i.e., the _id member of the left hand operand. Since you member operator isn't const, the compiler lets you do the modification. This is probably not what you intended to do. You probably rather wanted to write:
Point Point::operator+ (const Point& p) const
{
cout << "Operator + called, returning a new object\n";
return Point
(
_id + "+" + p._id,
_x+p._x,
_y+p._y
);
}
... which creates a suitable temporary string with the desired value (I also replaced the excessive use of std::endl).
This line in the operator+ overload:
_id.append("+").append(p._id),
You have to be very careful here, you are currently in an object (in your example this would be the G object). append actually alters the local string, so your code is appending + then p._id then deep copying that to the returned value.
A quick fix is to change this to a temporary that holds what you need:
_id + "+" + p._id
To avoid problems like this in the future, you should declare operator overloads as a friend method so it's extremely clear what you're operating on.
friend Point operator+ (const Point& lhs, const Point& rhs)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
lhs._id.append("+").append(rhs._id), //COMPILER ERROR! We're modifying the const "lhs"!
lhs._x+rhs._x,
lhs._y+rhs._y
);
}
So let's change this to:
friend Point operator+ (const Point& lhs, const Point& rhs)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
lhs._id + "+" + rhs._id, // no longer modifying lhs -- all is well!
lhs._x+rhs._x,
lhs._y+rhs._y
);
}
i'd like to ask something rather difficult for me; I have to make a calendar-type program, but with an overloaded '+=' operator.
So it goes like this:
template<typename T1,typename T2,typename T3> //int,int,int
class T_sort_data{
T1 p1;
T2 p2;
T3 p3;
public:
T_sort_data(){
cout << "\n\t Constructed at [" << this << "]\n";};
/ friend ostream& operator<<(ostream& os,const T_sort_data& obj) // get function
{
os << "\nDay : " << obj.p1 << " \n";
os << "Month : " << obj.p2 << " \n";
os << "Year : " << obj.p3 << " \n";
return os;
}*/
void set_date(){
int dd,mm,yy;
cout << "\n\n\tPlease input the day, the month and the year : \n\n";
cin >> dd >> mm >> yy;
p1 = dd;
p2 = mm;
p3 = yy;
}
// validator here, which works ...
T_sort_data<int,int,int>& operator+=(const T_sort_data<int,int,int>& second)
{
p1+=second.p1;
return *this;
}
friend istream& operator>>(istream& is, T_sort_data& obj) // set function
{
is >> obj.p1;
is >> obj.p2;
is >> obj.p3;
return is;
}
~T_sort_data(){
cout << "\n\t Deconstructed [" << this << "]\n";};
};
int main(){
T_sort_data<int,int,int> * a = new T_sort_data<int,int,int> ;
bool more = true;
string answ;
a->set_date();
//cin >> a; (this doesn't work)
//validator goes here
//a += a; (this, again, doesn't work)
delete a;
return 0;
}
Whenever I make an object using "T_sort_data a;" those operations work fine, but whenever I use "T_sort_data * a = new T_sort_data;"
shit hits the fan.
Can anyone help me with this?
You didn't post exactly what is going wrong so I have to infer that from the code.
The issue that you're running into is that overloaded operators work on instances or references to objects, not on pointers to objects. In the cases where your code doesn't work, you're dealing with pointers to objects. So, in order to use your overloaded operators, you need to dereference the pointer (effectively turning it from a pointer pointing to a value into the value itself) before applying the operator, for example:
cin >> *a;
or
*a += *a;
T_sort_data a is a variable of type T_sort_data.
T_sort_data * a is a variable of type pointer to T_sort_data.
Your overloaded operators expect their operands to be of type T_sort_data, not pointer to T_sort_data. Use the unary * operator to dereference the pointers, so that the operand types are what the operators expect.
This is pretty fundamental. Here's the same thing with int and std::cout: http://codepad.org/N07Xckdy