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.
Related
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I'm trying to learn C++ and had a question about returning arrays in C++. I know that in this case perhaps Vector may be better and that there is no need for a getter method as the fields are visible within the same class but I'm trying to learn about memory management so I'll use them.
class Color {
double r;
double g;
double b;
public:
Color(int a, int aa, int aaa) {
r = a;
g = aa;
b = aaa;
}
bool operator==(const Color &other) {
double *otherCol = other.getter();
return otherCol[0] == r && otherCol[1] == g && otherCol[2] == b;
}
double* getter() const {
double second[3] = {r,g,b};
return second;
}
};
int main() {
Color col1(23, 54, 200);
Color col2(23, 54, 200);
cout << (col1 == col2) << endl;
return 0;
}
This code should print out a 1 if the RGB colors are the same and 0 otherwise. But it does not print a 1. To debug, I added the following lines (twice on purpose) right before the return statement in operator==:
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
Oddly enough, the results are different:
23 54 200
6.91368e-310 6.91368e-310 3.11046e-317
Can someone please tell me what causes this and what would be a reasonable remedy that does not rely on Vector or dynamic allocation of memory? Let's assume that we don't want to pass in an array into getter() to update.
In getter you are returning the address of a local variable which results in undefined behavior so you are getting random memory. If you return a pointer you have to do something like new the variable in the called function and delete it after the function returns.
Or you could make second a class member which would keep it from going out of scope.
You could also pass the array in as a parameter.
Here is one program taken from a textbook featuring copy constructors:
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace std;
class point
{
private:
int x,y;
public:
point(int ox =0, int oy =0)
{
cout << " Make object" << this << endl;
cout << " Using default constructor \n";
x = ox, y = oy;
}
point(const point &p)
{
cout << " Make object" << this << endl;
cout << " Using copy constructor \n";
x = p.x, y = p.y;
}
void move(int dx, int dy);
void display();
};
point fct(point a);
int main()
{
point a(5,2);
a.display();
point b = fct (a);
b.display();
getch();
return 0;
}
void point::move(int dx, int dy)
{
x += dx, y += dy;
}
void point::display()
{
cout << "Coordinates :" << x << " " << y << "\n";
}
point fct(point a)
{
point b=a;
//b.move(2,3);
return b;
}
It should be noted that the copy constructor is of the form : point (const point &p) instead of point (point &p) (the latter is what's in the textbook, but couldn't compile so I had to switch to the first one, but still I can't understand why :( )
The textbook said that there will be 3 lines of "Using copy constructor" , corresponding to 3 calls to the copy constructor. I think the reason for that is, when you call: b = fct(a)
The function "fct" makes a copy of a (pass-by-value), therefor one call
The line : point b = a : again, a copy constructor is invoked
The return value is then copied into b (the variable in main, not the one in fct) this is 3rd one.
However upon execution, there is only 2 calls. Can anyone give me a good explaination on this?
Two copies occur because Named Return Value Optimization (NRVO) elides one of the copies.
point fct(point a)
{
point b=a;
return b;
}
point b = fct (a);
The first copy is the one from the argument a in main to the parameter a in fct. This occurs because the point is taken by-value.
The second copy is from a to b inside func.
The copy which is elided is the one in returning b by value. In this case, b can be directly allocated into the b at the call site, so no copy takes place.
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 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+(...)
This question already has answers here:
Uninitialized values being initialized?
(7 answers)
Closed 8 years ago.
I'm doing some testing...
Firstly I post my source code
the .h file
class Complex{
private:
int r = 0;//initializer
int i ;
public:
Complex(int , int I = 0);
Complex();
void print();
void set(int, int I = 1);
static void print_count();
static int count;
};
the .cpp file
#include <iostream>
#include "complex.h"
int Complex::count = 1;
Complex::Complex(int R , int I){
r = R;
i = I;
count++;
std::cout << "constructing Complex object...count is " << Complex::count << std::endl;
}
Complex::Complex(){//default constructor
std::cout << "default constructor is called..." << std::endl;
}
void Complex::print(){
std::cout << "r = " << r << ';' << "i = " << i << std::endl;
return;
}
void Complex::set(int R, int I /*= 2*/){//will be "redefaulting", an error
r = R;
i = I;
return;
}
void Complex::print_count(){//static
Complex::count = -1;//jsut for signaling...
std::cout << "count is " << count << std::endl;
return;
}
the main function
#include <iostream>
#include "complex.h"
int main(){
Complex d;//using default constructor
d.print();
/*Complex c(4, 5);*/
Complex c(4);
//c.print();
/*c.set(2, 3)*/
c.print();
c.set(2 );
c.print();
std::cout << "count is " << c.count << std::endl;//c can access member data
c.print_count();
c.count++;//
return 0;
}
consider the Complex object d constructed with default ctor
because the data member r is initialized using with 0, when executing d.print(),
r is expected to be 0
and i isn't, so I expected it to be garbage value
but when I'm testing, one strange thing happens.
if I eliminate this and the following lines of code in the main file:
std::cout << "count is " << c.count << std::endl;//c can access member data
then d.print() will give the value of i as 32767 on my system, which I guess it's a garbage value;
but once that line is added, d.print() just give i's value to 0 on my system.
I don't get it. I hasn't set, modiify or initialize i's value, why should it be 0?
or, it is also a garbage value?
or, calling one of those function corrupts the value of i?
how is the thing run behind the scene here?
thx for helping.
0 is just as garbage value as any other. Don't make the mistake of thinking otherwise.
Formally, reading an uninitialized variable is undefined behavior, so there's no point in wondering about it: just fix it by initializing the variable properly.