clarray.h

#ifndef CLARRAY_H #define CLARRAY_H #include <iostream> #include <QString> using std::cout; using std::cin; using std::endl; class array { private: int* ptr; int size; QString name = "tmp_obj"; public: array(int s, QString name){ size = s; ptr = new int[s]; this->name = name; } array(int s, int* p){ size = s; ptr = p; } ~array(){ cout << "destructor " << name.toStdString() << endl; delete[] ptr; } int& operator[](const int& j){ return *(ptr+j); } array operator=(const array& cl){ if(this!= &cl){ size = cl.size; delete[] ptr; ptr = new int[size]; *ptr = *cl.ptr; // для отладки пусть size == 1 } cout << "= " << *this->ptr << endl; return *this; } }; #endif // CLARRAY_H 

main.cpp

 #include <QCoreApplication> #include <iostream> #include <clarray.h> using std::cout; using std::cin; using std::endl; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); const int ASIZE = 1; array *cl = new array(ASIZE, "c1"); array *c2 = new array(ASIZE, "c2"); for(int i = 0; i < ASIZE; i++) (*cl)[i] = i*i; *c2 = *cl; //сразу после присваивания срабатывает деструктор c2 for(int i = 0; i < ASIZE; i++) cout << "c1: " << (*cl)[i] << " "; cout << endl; for(int i = 0; i < ASIZE; i++) cout << "c2: " << (*c2)[0] << " "; cout << endl; delete cl; delete c2; // return a.exec(); } 

Output

 = 0 destructor c2 c1: 0 c2: -572662307 destructor c1 destructor c2 

Another throws the exception _crtisvalidheappointer (block) , as I understand it because of the fact that I am addressing the freed memory.

Question: Why does the destructor work right after assignment?

2 answers 2

The assignment operator of this class returns a temporary object, which is deleted after calling this assignment operator.

  array operator=(const array& cl){ ^^^^^^ if(this!= &cl){ size = cl.size; delete[] ptr; ptr = new int[size]; *ptr = *cl.ptr; // для отладки пусть size == 1 } cout << "= " << *this->ptr << endl; return *this; } 

In addition, as a result of this proposal

 *ptr = *cl.ptr; // для отладки пусть size == 1 

there is a memory leak.

Also, your class is defined in such a way that it is difficult to determine how many elements of a dynamically distributed array were initialized and how many are not. In general, in this assignment statement, you must copy the actual elements of the array located on the right-hand side of the assignment sign to the target array.

As for the call to the destructor, you should declare the assignment operator as follows, that is, return the object reference

  array & operator=(const array& cl); ^^^ 

This constructor

 array(int s, int* p){ size = s; ptr = p; } 

also incorrect, because the class object must dynamically allocate memory for its array. Otherwise, a collision arises: who owns the pointer, and who is responsible for deleting the array pointed to by the pointer?

In addition, you should also define a copy constructor.

As for constructors, you could define them as follows.

 #include <algorithm> //... array(int s, QString name) : size( s ), name( name ) { ptr = new int[s]; std::fill( ptr, ptr + size, 0 ); } array(int s, int* p) : size( s ) { ptr = new int[s]; std::copy( p, p + s, ptr ); } 

    Well, see for yourself: what does your operator return?

     array operator=(const array& cl){ ... return *this; } 

    Exactly! array , not a link to it. So return *this; calls the copy constructor, and returns a copy of the array object ... which is immediately destroyed — you don't need it.
    Well, since you don’t have a copy constructor, the default copy constructor is called - it copies the pointer (the so-called shallow copy). The destructor deletes it, and your с1 remains with a pointer to the remote memory ...

    That's all.