I am learning operator overloading and I read somewhere that when you assign a r-value to object then it creates a temporary object but this program stops after calling constructor for r-value.
Class.h
class Foo{
int *num;
public :
Foo(int x);
Foo& operator=(Foo &&rhs);
Foo& operator=(const Foo &rhs);
Foo(Foo &f);
Foo(Foo &&f);
void set(int x);
void show();
~Foo();
};
Class.cpp
#include <iostream>
#include "class.h"
#include <cstring>
Foo::Foo(int x){
num = new int;
*num = x;
std::cout << "Constructor for " << *num << std::endl;
};
Foo::~Foo(){
std::cout << "Destructor for " << *num << std::endl;
delete num;
}
void Foo::show(){
std::cout << *num << std::endl;
}
void Foo::set(int x){
*num = x;
std::cout << "INSIDE SETTER" << std::endl;
}
Foo& Foo::operator=(Foo &&rhs){
num = rhs.num;
rhs.num = nullptr;
return *this;
}
Foo& Foo::operator=(const Foo &rhs){
*num = *rhs.num;
return *this;
}
Foo::Foo(Foo &f){
num = new int;
*num = *f.num;
std::cout << "Copy constructor used " << std::endl;
}
Foo::Foo(Foo &&f)
: num{f.num}{
std::cout << "Move constructor used " << std::endl;
f.num = nullptr;
}
int main(){
Foo f1(10);
Foo f2(20);
Foo f3(30);
f1.show();
f2.show();
f3.show();
f1 = 60;
f1.show();
f2.show();
f3.show();
return 0;
}
Program stops after calling constructor for 60.
OUTPUT
Constructor for 10
Constructor for 20
Constructor for 30
10
20
30
Constructor for 60
[Done] exited with code=3221225477 in 1.458 seconds
It works when I use char *str instead of int *num
CodePudding user response:
Your problem is in the destructor. It tries to access *num
, but move assignment operator sets num
to nullptr
.
Either guard logging against nullptr
(there is no need to guard delete
, as it is guaranteed to work properly on null pointers):
Foo::~Foo(){
if (num) {
std::cout << "Destructor for " << *num << std::endl;
} else {
std::cout << "Destructor for null pointer" << std::endl;
}
delete num;
}
Or use swap in move assignment and let rhs
to delete it eventually(this also will fix memory leak: you never delete old value of num
)
Foo& Foo::operator=(Foo &&rhs)
{
std::swap(num, rhs.num);
return *this;
}
Output for swap
solution:
Constructor for 10
Constructor for 20
Constructor for 30
10
20
30
Constructor for 60
Destructor for 10
60
20
30
Destructor for 30
Destructor for 20
Destructor for 60