Class destructor is causing problem with overloading + operator - c++

I can't figure out what is the problem with my C++ class (using Visual Studio). Visual Studio is not giving any desired output, just saying " exited with code -1073741819". I created a class named Complex using raw pointers, when no-args or parameterized constructor is called, memory is allocated using new int and when variable goes out of scope, destructor deallocates memory using delete keywords. The only problem i am facing is that, my + operator overloading causing problem and i am pretty sure that this problem is related to destructor, when i remove destructor code, + operator works just fine. Or when I don't use + operator, also then program works fine. Please help me by figuring out code. Please don't say to me that "you don't need raw pointers here", actually i have been told to do so (using only pointers). I am stuck on this for many hours.
Here is my code, please go through it , including + operator overloading code and destructor code.
#include<iostream>
using namespace std;
class Complex {
private:
int *real;
int *complex;
public:
// some declarations
Complex();
Complex(int, int);
Complex(const Complex& source);
Complex operator+ (const Complex& rhs);
Complex& operator= (const Complex& rhs);
void disp() {
cout << "(" << *real << "," << *complex << ")" << endl;
}
// destructor
~Complex() {
delete real;
real = nullptr;
delete complex;
complex = nullptr;
}
};
// no-args constructor
Complex::Complex() {
real = new int;
*real = 0;
complex = new int;
*complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {
*real = x;
*complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
// overloading + operator
Complex Complex::operator+ (const Complex &rhs) {
int a, b;
a = *(this->real) + *(rhs.real);
b = *(this->complex) + *(rhs.complex);
Complex temp(a,b);
return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
*(this->real) = *(rhs.real);
*(this->complex) = *(rhs.complex);
return *this;
}
int main() {
Complex n1(5,-9);
Complex n2(5,-1);
Complex n3;
n3=n1 + n2;
n3.disp();
return 0;
}

You don't allocate any memory in your copy constructor, so your assignments happen to uninitialized memory.
Complex::Complex(const Complex& source) {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
If I change it to this:
Complex::Complex(const Complex& source) : Complex() {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
Your program outputs (10,-10)
EDIT: Question in the comments.
I have added a few printouts to your program to show exactly what is going on:
#include<iostream>
using namespace std;
class Complex {
private:
int* real;
int* complex;
public:
// some declarations
Complex();
Complex(int, int);
Complex(const Complex& source);
Complex operator+ (const Complex& rhs);
Complex& operator= (const Complex& rhs);
void disp() {
cout << "(" << *real << "," << *complex << ")" << endl;
}
// destructor
~Complex() {
std::cout << "destructor" << std::endl;
delete real;
real = nullptr;
delete complex;
complex = nullptr;
}
};
// no-args constructor
Complex::Complex() {
std::cout << "constructor" << std::endl;
real = new int;
*real = 0;
complex = new int;
*complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {
std::cout << "(x,y)constructor" << std::endl;
*real = x;
*complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) : Complex() {
std::cout << "copy constructor" << std::endl;
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
// overloading + operator
Complex Complex::operator+ (const Complex& rhs) {
std::cout << "op+" << std::endl;
int a, b;
a = *(this->real) + *(rhs.real);
b = *(this->complex) + *(rhs.complex);
Complex temp(a, b);
return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
std::cout << "op=" << std::endl;
*(this->real) = *(rhs.real);
*(this->complex) = *(rhs.complex);
return *this;
}
int main() {
Complex n1(5, -9);
Complex n2(5, -1);
Complex n3;
n3 = n1 + n2;
n3.disp();
return 0;
}
Now running your program results this:
constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
constructor
copy constructor
destructor
op=
destructor
(10,-10)
destructor
destructor
destructor
As you can see, there is a "copy constructor" in there. Specifically this line: n3 = n1 + n2; results in this printout:
op+ // n1 + n2
constructor // base constructor from param constructor
(x,y)constructor // constructing the return value: Complex temp(a, b);
constructor // base constructor from copy constructor
copy constructor // copying from temp to the return value
destructor // destroying temp
op= // assigning the return value to n3
destructor // destroying the return value
Do note btw, that this was compiled in debug mode. If I compile in release mode the output changes:
constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
op=
destructor
(10,-10)
destructor
destructor
destructor
The pertinent point here is that the compiler managed to optimize out the copy constructor, by recognizing that there is no point in constructing temp only to then copy and destroy it. But this only happens when optimization is turned on.

I'm suspecting that your parameterized constructor is the problem... In your parameterized constructor, you are creating a Complex class object, which takes the *real and *complex pointers, pointing it to the passed in integers(x and y). No memory is allocated hence when your program ends, your destructor gets called and attempts to deallocate memory inside n1 and n2 that were never dynamically allocated.
I haven't touched C++ in a few months, so I could be wrong. Feel free to check and get back to me on your results.

Related

Why does assignment operator not work as expected?

UPD: I can see now how stupid this question is, it's just my misunderstanding of C++ constructions.
I got stuck with operator assignment problem - it doesn't work as expected. Here's the example code:
#include <iostream>
class TestClass{
private:
int pop;
public:
TestClass(){
std::cout<<"Default Constuctor\n";
}
TestClass(int i):pop(i){
std::cout<<"Param Constuctor\n";
}
TestClass &operator=(const TestClass &other){
std::cout<<"Assignment Operator \n";
return *this;
}
friend std::ostream &operator<<(std::ostream &out, TestClass &x);
};
std::ostream &operator<<(std::ostream &out, TestClass &x){
out<<" This is the TestClass with pop=" << x.pop <<"\n";
return out;
}
int main()
{
TestClass P0(333);
TestClass P_foo(555);
P_foo = P0;
std::cout << P0;
std::cout << P_foo;
return 0;
}
The result of this program is
Param Constuctor
Param Constuctor
Assignment Operator
This is the TestClass with pop=333
This is the TestClass with pop=555
So P_foo object preserves the initialized value 555.
If I comment out my custom assignment operator, the program works as expected.
Param Constuctor
Param Constuctor
This is the TestClass with pop=333
This is the TestClass with pop=333
What's wrong with my assignment operator function?
What's wrong with my assignment operator function?
At no point does *this get modified in your implementation of operator=:
TestClass &operator=(const TestClass &other){
std::cout<<"Assignment Operator \n";
return *this;
}
I see several issues with this code:
pop is not being initialized in the default constructor (which you are not calling, but you should still implement it properly, if you are going to implement it manually at all).
operator= is not updating the value of this->pop at all, which is the root cause of your issue. If you declare operator=, you are responsible for implementing it properly yourself, the compiler will not help you at all. But if you do not declare operator=, the compiler will auto-generate a default implementation that will assign a copy of the pop value for you.
operator<< should be taking the TestClass parameter by const reference.
Try this:
#include <iostream>
class TestClass{
private:
int pop;
public:
TestClass() : pop(0) { // <-- add this value!
std::cout << "Default Constructor\n";
}
TestClass(int i) : pop(i) {
std::cout << "Param Constructor\n";
}
TestClass& operator=(const TestClass &other){
std::cout << "Assignment Operator\n";
pop = other.pop; // <-- add this!
return *this;
}
friend std::ostream& operator<<(std::ostream &out, const TestClass &x);
};
std::ostream& operator<<(std::ostream &out, const TestClass &x){
out << " This is the TestClass with pop=" << x.pop << "\n";
return out;
}
int main()
{
TestClass P0(333);
TestClass P_foo(555);
P_foo = P0; // <-- this will work as expected now
std::cout << P0;
std::cout << P_foo;
return 0;
}
TestClass &operator=(const TestClass &other){
std::cout << "Assignment Operator \n";
pop = other.pop; // You need to add this
return *this;
}
The issue is that the assignment operator you defined doesn't assign anything to the instance it is called on.
Read through your operator again:
TestClass &operator=(const TestClass &other){
std::cout<<"Assignment Operator \n";
return *this;
}
You can see that two things happen. Assignment Operator is printed, and *this is returned. But your "other" TestClass is not used at all, and the data in this is never modified.
You can fix that by assigning to this->pop like so:
TestClass &operator=(const TestClass &other){
std::cout<<"Assignment Operator \n";
pop = other.pop; // Now this->pop will be assigned a new value from other.pop
return *this;
}
Now when you assign P_foo = P0, P_foo is successfully assigned the pop value from P0.

How can can I sort a vector of pointed-to values using std::sort()?

There is already the post sorting vector of pointers but this is not about a vector of pointers but rather about a vector of referencing pointers.
3 integer are put into a std::vector<int*> which is than sorted according to the values behind the pointers.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int a = 3;
int b = 2;
int c = 1;
std::vector<int*> vec;
vec.emplace_back(&a);
vec.emplace_back(&b);
vec.emplace_back(&c);
std::sort(vec.begin(), vec.end(), [](const int* a, const int* b) {
return *a < *b;
});
std::cout << "vec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n';
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
}
however, it seems that only the vector was sorted as the output shows:
vec = 1, 2, 3
abc = 3, 2, 1
I think the reason is that std::sort(), while comparing correctly, simply assigns adresses instead of the values. What is wrong here? Why can't I sort this vector of pointed-to values?
The next part is rather TL,DR as it shows my approach to solve this. An easy task that reveals itself to be rather frustratingly complicated. #Bathsheba's answer points out that it is not possible. So the next parts, initially considered to be the presentation of my attempt, might now be considered to be the reason why it is not possible.
My idea is to make a pointer class wrapper to provide my own contructors and assignement operators. std::sort() behaves differently if the size of the container is small (<= 32 on my system) but in both cases there are assignements and moves happening - as this small snippet from the _Insertion_sort_unchecked (from <algorithm>) function shows.
(_BidIt == std::vector<int*>::iterator and _Iter_value_t<_BidIt> == int*)
_BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred)
{ // insertion sort [_First, _Last), using _Pred
if (_First != _Last)
{
for (_BidIt _Next = _First; ++_Next != _Last; )
{ // order next element
_BidIt _Next1 = _Next;
_Iter_value_t<_BidIt> _Val = _STD move(*_Next);
if (_DEBUG_LT_PRED(_Pred, _Val, *_First))
{ // found new earliest element, move to front
_Move_backward_unchecked(_First, _Next, ++_Next1);
*_First = _STD move(_Val);
Let's make a class assignement_pointer that behaves like a pointer except that it assigns the values instead of the adresses.
template<typename T>
class assignement_pointer {
public:
assignement_pointer(T& value) {
this->m_ptr = &value;
std::cout << "<T>& constructor\n";
}
assignement_pointer(const assignement_pointer& other) {
this->m_ptr = other.m_ptr;
std::cout << "copy constructor\n";
}
assignement_pointer(assignement_pointer&& other) {
std::cout << "move assignement constructor >> into >> ";
*this = std::move(other);
}
assignement_pointer& operator=(const assignement_pointer& other) {
*this->m_ptr = *other.m_ptr;
std::cout << "copy assignement operator\n";
return *this;
}
assignement_pointer& operator=(assignement_pointer&& other) {
std::swap(this->m_ptr, other.m_ptr);
std::cout << "move assignement operator\n";
return *this;
}
T& operator*() {
return *this->m_ptr;
}
const T& operator*() const {
return *this->m_ptr;
}
private:
T* m_ptr;
};
As you can see there are also temporary std::cout's to see which constructors / assignement operators were called while going through std::sort() in the main:
///...
std::vector<assignement_pointer<int>> vec;
vec.reserve(3);
vec.emplace_back(assignement_pointer(a));
vec.emplace_back(assignement_pointer(b));
vec.emplace_back(assignement_pointer(c));
std::cout << "\nsort()\n";
std::sort(vec.begin(), vec.end(), [](const assignement_pointer<int>& a, const assignement_pointer<int>& b) {
return *a < *b;
});
std::cout << "\nvec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n';
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
giving the output:
<T>& constructor
move assignement constructor >> into >> move assignement operator
<T>& constructor
move assignement constructor >> into >> move assignement operator
<T>& constructor
move assignement constructor >> into >> move assignement operator
sort()
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
move assignement operator
vec = 1, 2, 3
abc = 3, 2, 1
std::sort() calls only move functions.
again, vec is sorted but not a, b, c
the last point makes sense, because since only move functions are called the copy assignement operator assignement_pointer& operator=(const assignement_pointer& other); (which does the value assignement) is never called. The unnecessary copy constructor and assignement operator can be removed:
template<typename T>
class assignement_pointer {
public:
assignement_pointer(T& value) {
this->m_ptr = &value;
}
assignement_pointer(const assignement_pointer& other) = delete;
assignement_pointer& operator=(const assignement_pointer& other) = delete;
assignement_pointer(assignement_pointer&& other) {
std::cout << "move assignement constructor >> into >> ";
*this = std::move(other);
}
assignement_pointer& operator=(assignement_pointer&& other) {
std::swap(this->m_ptr, other.m_ptr);
std::cout << "move assignement operator\n";
return *this;
}
T& operator*() {
return *this->m_ptr;
}
const T& operator*() const {
return *this->m_ptr;
}
private:
T* m_ptr;
};
Now std::sort() inner processes are rather complicated but in the end it comes down to failing at an operation like std::swap():
int main() {
int a = 3;
int b = 2;
std::vector<assignement_pointer<int>> vec;
vec.reserve(2); //to avoid re-allocations
vec.emplace_back(assignement_pointer(a));
vec.emplace_back(assignement_pointer(b));
std::cout << "swap()\n";
assignement_pointer<int> ptr_a{ a };
assignement_pointer<int> ptr_b{ b };
std::swap(ptr_a, ptr_b);
std::cout << "\nptrs = " << *ptr_a << ", " << *ptr_b << '\n';
std::cout << "a, b = " << a << ", " << b << '\n';
}
and as this output shows:
move assignement constructor >> into >> move assignement operator
move assignement constructor >> into >> move assignement operator
swap()
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
ptrs = 2, 3
a, b = 3, 2
it's that sitation that only the pointers are switched but not the original variables. std::swap is basically
_Ty _Tmp = _STD move(_Left);
_Left = _STD move(_Right);
_Right = _STD move(_Tmp);
explaining the
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
the move assignement operator simply swaps the pointers so creating a temporary variable doesn't do anything.
I see two possible solutions to this:
make the move assignement operator not swap pointers but rather values.
implement my own swap() for the class
but both don't work.
the move assignement operator can't swap values because the initial m_ptr from this-> class is always nullptr and I would rather not dereference this.
std::sort() never uses std::swap() but instead just std::move()s from all over the place. (as already partially seen by _Insertion_sort_unchecked).
You'll need to roll your own sort function to do this.
The callback lambda is used to evaluate the ordering, but you need to tweak the part that does the actual exchange of elements: and the C++ standard library sort does not support your doing that.
Fortunately a quick sort without any bells and whistles (such as pre-randomisation) comes out in a few tens of lines, so this is not a particularly onerous task to complete.
Just retain a copy of the original vector of pointers and copy the sorted values over:
std::vector<int*> original = vec; // Do this before the std::sort
Then after you print a,b,c:
std::vector<int> xfer;
for (auto ptr : vec) {
xfer.push_back(*ptr);
}
auto it = std::begin(xfer);
for (auto ptr : original) {
*ptr = *it++;
}
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
Output:
abc = 1, 2, 3

Why is copy constructor called here?

I have the following code:
template<class T = char>
class String
{
public:
// Default constructor
String()
: buffer(nullptr),
len(0)
{
cout << "Default constructor" << endl;
}
// Constructor
String(const char* s)
{
cout << "Constructor (const char*)" << endl;
//...
}
// Virtual destructor.
virtual ~String()
{
cout << "Destructor" << endl;
len = 0;
delete[] buffer;
}
// Copy constructor
String(const String& s)
{
cout << "Copy constructor" << endl;
buffer = new T[s.len];
std::copy(s.buffer, s.buffer + s.len, buffer);
len = s.len;
}
// Copy assignment operator (uses copy and swap idiom)
String& operator=(String s)
{
cout << "Copy assignment operator (copy and swap idiom)" << endl;
std::swap(buffer, s.buffer);
return *this;
}
// Move constructor
String(String&& s)
{
cout << "Move constructor" << endl;
}
// compound assignment (does not need to be a member,
// but often is, to modify the private members)
String& operator+=(const String& rhs)
{
cout << "operator+=" << endl;
//...
return *this; // return the result by reference
}
// friends defined inside class body are inline and are hidden from non-ADL lookup
// passing lhs by value helps optimize chained a + b + c
// otherwise, both parameters may be const references
friend String operator+(String lhs, const String& rhs)
{
cout << "operator+" << endl;
lhs += rhs; // reuse compound assignment
return lhs; // return the result by value (uses move constructor)
}
private:
T* buffer;
size_t len;
};
int main()
{
String<> s("Hello ");
String<> s2("World");
// call copy constructor first?
String<> s3 = s + s2;
return 0;
}
And the output is:
Constructor (const char*)
Constructor (const char*)
Copy constructor
operator+
operator+=
Move constructor
Destructor
My question is why is the copy constructor called immediately in:
String<> s3 = s + s2;
A value copy of s is taken by friend String operator+(String lhs, const String& rhs), essentially because s is not an anonymous temporary and is therefore not an appropriate candidate for move construction. Taking that value copy requires the copy constructor.
To my understanding, the copy constructor is called to receive the return value of the + operator.

Getting garbage value while doing chaining of assignment of class objects, using assignment operator overloading which returns class object by value

In assignment operator overloading, If I return the object by reference like below
One& operator=( const One& obj).
Then program works fine.
But if when I return by value, like below
One operator=( const One& obj)
Then o1 gets garbage value. Can anybody explain why return by value does not work in assignment operator overloading?
class One
{
public:
One(int a1, int b1) {
a = a1; b = b1;
}
int a;
int b;
One operator=( const One& obj) {
cout<<"\nOperator= is called\n"; a = obj.a; b = obj.b;
}
};
int main()
{
One o1(5,5);
One o2(10,10);
One o3(15,15);
cout << "\no1.a=" << o1.a << ", o1.b=" << o1.b << endl;
o1 = o2 = o3;
cout << "\no1.a=" <<o1.a << ", o1.b=" << o1.b << endl;
cout << "\no2.a=" <<o2.a << ", o2.b=" << o2.b << endl;
cout << "\no3.a=" <<o3.a << ", o3.b=" << o3.b << endl;
return 0;
}
Output:
o1.a=-13360, o1.b=0
o2.a=15, o2.b=15
o3.a=15, o3.b=15
Why o1 object showing garbage value in case of return by value in assignment operator. It works fine when return by reference. why?
o1 = o2 = o3; is evaluated as o1 = (o2 = o3);
That requires o2 = o3 to return something, and o1 is set to that value. But your overload currently doesn't. (Formally it means that the behaviour of your code is undefined). If you rewrite to
One& operator=(const One& obj)
{
std::cout << "\nOperator= is called\n";
a = obj.a;
b = obj.b;
return *this; // i.e. return a reference to self.
}
then all will be well. That said, the cool cats will use
One& operator=(One obj/*pass by value to exploit compiler optimisations*/)
{
std::cout << "\nOperator= is called\n";
std::swap(*this, obj);
return *this;
}
Reference: What is the copy-and-swap idiom?
The code of the = operator should be this:
One & operator=(const One& obj)
{
cout << "\nOperator= is called\n";
a = obj.a;
b = obj.b;
return *this;
}
One operator=( const One& obj)
{ cout<<"\nOperator= is called\n"; a = obj.a; b = obj.b; }
You do not have any return expression in your function definition, resulting in undefined behavior. That's why the operator does not work as it should.
In case you are using the gcc compiler, I would suggest you enable the -Wall option, which would have produced a warning, indicating the failure. In case you are using sth different there's probably an equivalent option available.
You may also want to take a look at the Copy-and-Swap Idiom which provides an advanced insight in the creation of a properly working copy-assignment operator.

Understanding C++ copy constructor behavior

This is my code:
#include <iostream>
using namespace std;
class A
{
int i;
public:
A(int v) : i(v) { }
A(const A& r) : i(r.i) {
cout << "Copy constructor" << endl;
}
A operator=(const A& r) {
cout << "Assignment function" << endl;
return r;
}
void show() {
cout << i << endl;
}
};
int main()
{
A a(1);
A b(2);
a = b;
a.show();
return 0;
}
Value of b is 2 and value of a is 1. In 'main', b is copied into a and this the output I get:
Assignment function
Copy constructor
This is understandable, but the output for a.show() comes out be 1. I can't understand this. How? Because b is copied into a using the copy constructor so shouldn't a.i have the value of b.i?
b is copied into a using the assignment operator, not the copy constructor. And your assignment operator doesn't assign i, so a.i keeps its original value.
The copy constructor you are seeing is for the return value of operator=. It is more customary to return the left-hand-side by reference, not the right-hand-side by value:
A& operator=(const A& r) {
cout << "Assignment function" << endl;
i = r.i;
return *this;
}
When you define the assignment operator you have to do all of the work to copy the data.
A operator=(const A& r) {
cout << "Assignment function" << endl;
i = r.i;
return r;
}
so a = b is calling your assignment operator (obviously, hence your output). But right now it isn't copying anything.
The assignment operator doesn't do anything to the "assigned to" object. The copy constructor call you see reported is from the creation of the assignment return value.
Your copy assignment should probably look loke this:
A& A::operator= (A const& other) {
// output
this->i = other.i;
return *this;
}