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
Ещё кидает исключение _crtisvalidheappointer(block), как я понимаю из-за того что я обращаюсь к освобожденному участку памяти.
Вопрос: почему сразу после присваивания срабатывает деструктор?
Оператор присваивания данного класса возвращает временный объект, который и удаляется после вызова этого оператора присваивания.
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;
}
Кроме того в результате данного предложения
*ptr = *cl.ptr; // для отладки пусть size == 1
имеется утечка памяти.
Также ваш класс определен таким образом, что трудно определить, сколько элементов динамически распределенного массива было инициализировано, а сколько нет. В общем случае в данном операторе присваивания вы должны копировать актуальные элементы массива, находящегося в правой части от знака присваивания в целевой массив.
Что касается вызова деструктора, то вам следует объявить оператор присваивания следующим образом, то есть возвращать ссылку на объект
array & operator=(const array& cl);
^^^
Данный конструктор
array(int s, int* p){
size = s;
ptr = p;
}
также неверный, так как объект класса должен динамически выделять память для своего массива. Иначе возникает коллизия: кто является владельцем указателя, и кто ответственен за удаления массива, адресуемого указателем?
К тому же вам следует также определить конструктор копирования.
Что касается конструкторов, то вы могли бы определить их следующим образом
#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 );
}
Ну смотрите сами: что возвращает ваш оператор?
array operator=(const array& cl){
...
return *this;
}
Именно! array, а не ссылку на него. Так что return *this; вызывает конструктор копирования, и возвращает копию - объект array... который тут же уничтожается - он вам оказался не нужен.
Ну, а раз конструктора копирования у вас нет, то вызывается конструктор копирования по умолчанию - который копирует указатель (т.н. поверхностное копирование). Деструктор его удаляет, и ваш с1 остается с указателем на удаленную память...
Вот и всё.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники