I was told in this answer to delete the member myValue in the destructor. But if I add it I am getting an exception. From the console messages it seems to be entering the destructor at two moments with the same object(!?)
Note: The code is my attempt to an exercise. In it we are given a code to which we can only add to it. Essentially the content of the main and the constructor without parameters is that is given. The rest is what I am adding to it to make it work.
My guess is that a copy of the object made during some function call is destroying the same myValue after exiting the function call. How is the right way to preserve the data pointed to by two objects in this case?
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class MyFancyInt
{
public:
// A constructor that inputs a value for initialization, so that line /*1*/ makes sense.
MyFancyInt(int x) : myValue(new int(x))// The part after the : initializes myValue to point to the newly created int with value x.
{
cout << "Constructor that initializes with myValue = " << x << endl;
};
//Destructor.
~MyFancyInt()
{
cout << "A MyFancyInt destroyed that had the myValue = "<< this->myValue<< " pointing to a "<< *(this->myValue) << endl;
//delete myValue;
};
//A 'Copy Constructor', so that line /*3*/ makes sense. Aparently C++ creates default copy constructors.
//A copy constructor input an already existing MyFancyInt, creates a new MyFancyInt and initializes it with the data of the former.
MyFancyInt(MyFancyInt& x)
{
myValue = x.myValue;
};
//The construtor without parameters already given in the exercise.
MyFancyInt()
{
cout << "Default constructor" << endl;
myValue = 0;
}
// Friend function to overload the operator +. This one takes two MyFancyInt. It is not needed. It can be commented out.
friend MyFancyInt operator+(MyFancyInt &x, MyFancyInt &y);
// Friend function to overload the operator +. This one takes an int and a MyFancyInt. It is needed for line /*6*/.
friend MyFancyInt operator+(int x, MyFancyInt &y);
// Friend function to overload the operator +. This one takes a MyFancyInt and an int. It is needed for line /*5*/.
friend MyFancyInt operator+(MyFancyInt &x, int y);
// Friend function to overload the output stream operator <<. It is needed for the printing in line /*7*/.
friend ostream& operator<<(ostream& os, const MyFancyInt& x);
// Overloading the operator =. It is needed for line /*2*/, /*5*/, and /*6*/.
MyFancyInt& operator=(const MyFancyInt &x);
private:
int* myValue;
};
MyFancyInt operator+(MyFancyInt &x, MyFancyInt &y)
{
cout << "MyFancyInt + MyFancyInt = " << x.myValue << " + " << y.myValue << "= " << *(x.myValue) << " + " << *(y.myValue) << endl;
MyFancyInt z=MyFancyInt(*(x.myValue) + *(y.myValue));
cout << "= " << *(z.myValue) << endl;
return z;
};
MyFancyInt operator+(int x, MyFancyInt &y)
{
cout << "int + MyFancyInt = " << x << " + " << y.myValue << " = " << x << " + " << *(y.myValue)<< endl;
MyFancyInt z = MyFancyInt(x + *(y.myValue));
cout << " = " << *(z.myValue) << endl;
return z;
};
MyFancyInt operator+(MyFancyInt &x, int y)
{
cout << "MyFancyInt + int = " << x.myValue << " + " << y << " = " << *(x.myValue) << " + " << y << endl;
MyFancyInt z = MyFancyInt(*(x.myValue) + y);
cout << " = " << *(z.myValue) << endl;
return z;
};
ostream& operator<<(ostream& os, const MyFancyInt& x)
{
os << *(x.myValue);
return os;
}
MyFancyInt& MyFancyInt::operator=(const MyFancyInt &x)
{
cout << "Entering the assigment operator." << endl;
myValue = x.myValue;
return *this;
};
int _tmain(int argc, _TCHAR* argv[])
{
MyFancyInt mfi1(1); /*1*/
MyFancyInt mfi2 = mfi1; /*2*/
MyFancyInt mfi3(mfi1); /*3*/
MyFancyInt mfi4; /*4*/
mfi4 = mfi3 + 2; /*5*/
mfi4 = 3 + mfi3; /*6*/
cout << mfi4 << endl; /*7*/
return 0;
}
The way your copy constructor is written, when you copy an object, both objects will be pointing to the same address and both will try to delete it.
Related
how to overload assignment operator to satisfy ob1=ob2=ob3 (ob1,ob2,ob3 are objects of same class) where we have no concern for (ob2 = ob3) which is similar to (ob2.operator=(ob3)) but we need a parameter of type class when we are assigning this result to ob1 which is similar to (ob1.operator=(ob2.operator=(ob3)) below is the code that gives me error
#include<bits/stdc++.h>
using namespace std;
class A
{
public:
int x;
int *ptr;
A()
{
}
A(int a, int *f)
{
x = a;
ptr = f;
}
void operator=(A&);
};
void A::operator=(A &ob)
{
this->x = ob.x;
*(this->ptr) = *(ob.ptr);
}
int main()
{
int *y = new int(3);
A ob1, ob2, ob3(5, y);
ob1 = ob2 = ob3;
cout << ob1.x << " " << *(ob1.ptr) << endl;
cout << ob2.x << " " << *(ob2.ptr) << endl;
cout << ob3.x << " " << *(ob3.ptr) << endl;
return 0;
}
Your asignement operator should return a reference to *this, and be defined as
A& operator=(const A&);
or, better, pass by value and use the copy-and-swap idiom
A& operator=(A);
For an excellent intro to operator overloading, see this.
We know that the fascinating class iostream is something too powerful.
it has overloded the insertion operator "<<" to take many datatypes:
ostream& operator(ostream&, int),
ostream& operator(ostream&, char)...
we cannot instantiaate ostream: ostream print;
because ostream because its most CTORSs are "protected-socoped" (cannot be accessed from outside).
the only Constructor we can call is ostream(streambuf*) which takes a pointer to another class object ( class streambuf);
I just wanted to mess up with this class:
#include <ostream>
using namespace std;
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << x; // normally works well and it prints the address that x points to but instead the program get in infinite loop or crushes!
return *x;
}
int main()
{
system("color 1f");
int* pVal = new int(57);
cout << *pVal << endl;
int* pX = new int(7);
cout << *pX << endl;
cout << *pVal << ", " << *pX << endl;
//cout << pVal << endl; // this doesn't work because my operator returns
//int and not a reference to ostream.
// and it is equal to: 0 << endl; which generates the same error
cout << pVal; // this works
// cout << endl << endl << endl;
return 0;
}
I overloaded the insertion operator to take an lvalue as a reference to an ostream object and a pointer to int as rvalue, I popup a message inside my function to get sure that it is invoked.
Note that I intentionally overloaded it to return int value so that no one can write:
out << pInt << *pInt << endl;
... but just:
out << pInt;
My problem, as you can see in the inline-comments above, is that whilst cout << x normally works well, instead the program get in infinite loop or crushes!
return *x;
Can anyone explain why I am getting the error?
The problem hapens because if you just cout << x, it will call your overloaded function over and over. It never returns.
Here's the solution (cast x to void*)
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << (void*)x;
return *x;
}
I have a class A:
class Sportist{
private:
string ime;
int godina_na_ragjanje;
int godisna_zarabotuvacka_EUR;
public:
Sportist(string i, int g_n_r, int g_z_EUR){
ime = i;
godina_na_ragjanje = g_n_r;
godisna_zarabotuvacka_EUR = g_z_EUR;
}
string getIme(){
return ime;
}
int getGodinaNaRagjanje(){
return godina_na_ragjanje;
}
int getGodisnaZarabotuvackaEUR(){
return godisna_zarabotuvacka_EUR;
}
};
And class B using the class A as public:
class Fudbaler:public Sportist{
private:
int broj_na_odigrani_natprevari;
int danocna_stapka;
public:
Fudbaler(string ime, int godina, int zarabotuvacka, int b, int d)
:Sportist(ime, godina, zarabotuvacka)
{
broj_na_odigrani_natprevari = b;
danocna_stapka = d;
}
float danok(){
return getGodisnaZarabotuvackaEUR() * danocna_stapka;
}
friend ostream& operator<<(ostream &os, Fudbaler F){
return os << "Ime: " << getIme() << endl
<< "Godina na raganje: " << getGodinaNaRagjanje() << endl
<< "Godisna zarabotuvacka(EUR): " << getGodisnaZarabotuvackaEUR() << endl
<< "Danok sto treba da plati: " << danok();
}
};
And I get 4 errors as described in title in these lines:
return os << "Ime: " << getIme() << endl
<< "Godina na raganje: " << getGodinaNaRagjanje() << endl
<< "Godisna zarabotuvacka(EUR): " << getGodisnaZarabotuvackaEUR() << endl
<< "Danok sto treba da plati: " << danok();
cannot call member function 'std::string Sportist::getIme()' without object
cannot call member function 'int Sportist::getGodinaNaRagjanje()' without object
cannot call member function 'int Sportist::getGodisnaZarabotuvackaEUR()' without object
cannot call member function 'float Fudbaler::danok()' without object
i would say the function should be changed to
friend ostream& operator<<(ostream &os, Fudbaler F){
return os << "Ime: " << F.getIme() << endl
<< "Godina na raganje: " << F.getGodinaNaRagjanje() << endl
<< "Godisna zarabotuvacka(EUR): " << F.getGodisnaZarabotuvackaEUR() << endl
<< "Danok sto treba da plati: " << F.danok();
}
I am not shure about operator overloading for the std::streams. i usually have done that outside of the class. From your error messages, you need to use the passed Fudbaler variable to access the methods of it.
Consider this piece of code and its output:
class test {
int a, b;
public:
test (int a, int b) : a(a), b(b) { cout << "Const" << endl;}
test (const test & t) {
cout << "Copy constructor" << endl;
cout << "Being copied to = " << this << " from " << &t << endl;
if (&t == this) {
cout << "returning" << endl;
return;
}
this->a = t.a;
this->b = 6;//t.b;
}
test operator=(const test & in) {
cout << "Assignment operator" << endl;
this->a = in.a;
this->b = in.b;
cout << "Being written to = " << this << " from "<< &in << endl;
return *this;
}
test get () {
test l = test (3, 3);
cout << "Local return " << &l << endl;
return l;
}
void display () {
cout << a << " " << b << endl;
}
};
int main () {
int i = 5, &ref = i;
test t(1,1), u(2,2);
u = t.get();
cout << "u address" << &u <<endl;
//cout << "u ka = " << &u << endl;
u.display();
}
Output:
Const
Const
Const
Local return 0x7fff680e5ab0
Assignment operator
Being written to = 0x7fff680e5a90 from 0x7fff680e5ab0
Copy constructor
Being copied to = 0x7fff680e5a80 from 0x7fff680e5a90
u address0x7fff680e5a90
3 3
I know the way to return from an assignment is by reference, but I was trying to understand how this works since I am a beginner to C++.
What is the address 0x7fff680e5a80 ? Where is this coming from ? Which object is calling the copy constructor here ? I would expect u (address 0x7fff680e5a90) to call it.
Lets follow your code (I modified your constructor to dump the constructed this).
First you isntantiate t and u.
Const at 0x7fffffffdeb0
Const at 0x7fffffffdea0
Then you call t.get, which initializes l.
Const at 0x7fffffffdec0
You then return l.
Local return 0x7fffffffdec0
The copy constructor that would normally happen at this point is elided.
Assignment operator from l to u
Being written to = 0x7fffffffdea0 from 0x7fffffffdec0
Then you are returning the assignment by value (you should return it by reference), so you copy from u to an output value that isn't stored (0x7fffffffde90 from u)
Copy constructor
Being copied to = 0x7fffffffde90 from 0x7fffffffdea0
And then you print u.
u address0x7fffffffdea0
Inside T.
To get rid of the confusing (and unessisary copy) you should return by reference when you do any assignment operator:
test& operator=(const test & in);
Your assignment operator is incorrect:
test operator=(const test & in) {
You should return by reference:
test &operator=(const test & in) {
The object at 0x7fff680e5a80 is a prvalue temporary object of type test that is returned from your (incorrect) assignment operator and immediately discarded:
test operator=(const test & in) {
cout << "Assignment operator" << endl;
this->a = in.a;
this->b = in.b;
cout << "Being written to = " << this << " from "<< &in << endl;
return *this;
} // ^-- copy constructor is called here
You can check this by taking an rvalue reference to the return value of the assignment operator:
auto &&temp = (u = t.get());
std::cout << "Address of temp: " << &temp << std::endl; // prints 0x7fffffffde90
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are copy elision and return value optimization?
I have the following program:
#include <iostream>
using namespace std;
class Pointt {
public:
int x;
int y;
Pointt() {
x = 0;
y = 0;
cout << "def constructor called" << endl;
}
Pointt(int x, int y) {
this->x = x;
this->y = y;
cout << "constructor called" << endl;
}
Pointt(const Pointt& p) {
this->x = p.x;
this->y = p.y;
cout << "copy const called" << endl;
}
Pointt& operator=(const Pointt& p) {
this->x = p.x;
this->y = p.y;
cout << "op= called" << endl;
return *this;
}
};
Pointt func() {
cout << "func: 1" << endl;
Pointt p(1,2);
cout << "func: 2" << endl;
return p;
}
int main() {
cout << "main:1" << endl;
Pointt k = func();
cout << "main:2" << endl;
cout << k.x << " " << k.y << endl;
return 0;
}
The output I expect is the following:
main:1
func: 1
constructor called
func: 2
copy const called
op= called
main:2
1 2
But I get the following:
main:1
func: 1
constructor called
func: 2
main:2
1 2
The question is: why doesn't returning an object from func to main call my copy constructor?
This is due to Return Value Optimization. This is one of the few instances where C++ is allowed to change program behavior for an optimization.