Спроектирвал класс:
class Mass{
public:
Mass ( int N, int *a ) {setMass( N, a );}
Mass ( Mass& t );
Mass& operator= ( Mass& t );
~ Mass ();
bool setMass( int N, int *a );
[skipped here]
private:
Mass ( ) {}
private:
int n, *a;
};
Mass& Mass::operator= ( Mass& t ) {
this->n = t.n; this->a = t.a;
z++;
return *this;
}
Как видно из кода я создал оператор поверхностного копирования.
после такого использования класса:
Mass *m2;
Mass *m1 = new Mass(10, a);
m2 = m1 = m2;
все работает, только при завершении программа падает. Из отладки выяснилось,
что это результат поверхностного копирования - в классе используется
динамический массив, и при завершении программы оператор delete используется к
высвобожденной памяти.
Мне необходимо использовать поверхностное копирование с целью экономии памяти
(массив может быть огромным).
Как разрешается подобное, подскажите, пожалуйста.
Помогите пожалуйста советом.
--
Best regards,
Arseniy Chaplinskiy
> class Mass{
> public:
> Mass ( int N, int *a ) {setMass( N, a );}
> Mass ( Mass& t );
> Mass& operator= ( Mass& t );
> ~ Mass ();
> bool setMass( int N, int *a );
>
> [skipped here]
>
>
> private:
> Mass ( ) {}
>
> private:
> int n, *a;
> };
>
> Mass& Mass::operator= ( Mass& t ) {
> this->n = t.n; this->a = t.a;
> z++;
> return *this;
> }
>
> Как видно из кода я создал оператор поверхностного копирования.
> после такого использования класса:
> Mass *m2;
> Mass *m1 = new Mass(10, a);
> m2 = m1 = m2;
> все работает, только при завершении программа падает. Из отладки
> выяснилось,
> что это результат поверхностного копирования - в классе используется
весьма странно, что получен именно такой результат,
B приведенном коде инициализирется указатель m1, потом
ему присваивается значение (неинициализированного, или
инициализированного нулем) указателя m1, и созданный
объект просто теряется. Оператор Mass& Mass::operator=
в данном случае не вызывается.
Даже если это присваивание не приводит к undefined behaviur,
то любые попытки работать с объектами через указатели m1 и
m2 скорее всего приведут к проблемам.
> динамический массив, и при завершении программы оператор delete
> используется к
> высвобожденной памяти.
> Мне необходимо использовать поверхностное копирование с целью экономии
> памяти
> (массив может быть огромным).
> Как разрешается подобное, подскажите, пожалуйста.
если я правильно понимаю твой замысел, то ИМХО самое
простое решение - это использовать boost::shared_array
#include <boost\shared_array.hpp>
class Mass
{
public:
typedef boost::shared_array<int> array_t;
Mass ( int N, array_t const & a )
{
setMass( N, a ); // не нужно ли проверить результат?
}
Mass ( Mass const& t )
:n( t.n )
,a( t.a )
{
}
Mass& operator= ( Mass const& t )
{
n = t.n;
a = t.a;
z++; // ???
return *this;
}
bool setMass( int N, array_t const& a );
private:
int n;
array_t a;
};
Cheers,
Serge
AC> class Mass{
AC> public:
AC> Mass ( int N, int *a ) {setMass( N, a );}
AC> Mass ( Mass& t );
AC> Mass& operator= ( Mass& t );
AC> ~ Mass ();
AC> bool setMass( int N, int *a );
AC> [skipped here]
AC> private:
AC> Mass ( ) {}
AC> private:
AC> int n, *a;
AC> };
AC> Mass& Mass::operator= ( Mass& t ) {
AC> this->n = t.n; this->a = t.a;
AC> z++;
AC> return *this;
AC> }
AC> Мне необходимо использовать поверхностное копирование с целью экономии
AC> памяти (массив может быть огромным).
AC> Как разрешается подобное, подскажите, пожалуйста.
Можно использовать подсчёт ссылок. Например, вместо int * a использовать
refptr * pa.
struct refptr
{
int count;
int * a;
};
При копировании делать ++(pa->count). В деструкторе --(pa->count), и если он
равен 0, убивать pa->a и pa.
With best regards, Dmitri Roschin.
Once (Wednesday November 01 2006) at 20:58 someone named Sergiy Kanilo wrote to
Arseniy Chaplinskiy. So, look here:
>> Mass *m2;
>> Mass *m1 = new Mass(10, a);
>> m2 = m1 = m2;
>> все работает, только при завершении программа падает. Из отладки
>> выяснилось,
>> что это результат поверхностного копирования - в классе используется
SK> весьма странно, что получен именно такой результат,
SK> B приведенном коде инициализирется указатель m1, потом
SK> ему присваивается значение (неинициализированного, или
SK> инициализированного нулем) указателя m1, и созданный
SK> объект просто теряется.
SK> Оператор Mass& Mass::operator=
SK> в данном случае не вызывается.
А в каком случае это происходит 7
SK> Даже если это присваивание не приводит к undefined behaviur,
SK> то любые попытки работать с объектами через указатели m1 и
SK> m2 скорее всего приведут к проблемам.
В том то и соль, что программа падает, когда вызываются деструкторы
экземпляров. Причем по переменным m2 и m1 удается работать ...
>> динамический массив, и при завершении программы оператор delete
>> используется к
>> высвобожденной памяти.
>> Мне необходимо использовать поверхностное копирование с целью
>> экономии
>> памяти
>> (массив может быть огромным).
>> Как разрешается подобное, подскажите, пожалуйста.
SK> если я правильно понимаю твой замысел, то ИМХО самое
SK> простое решение - это использовать boost::shared_array
спасибо за идею, проработаю. Может, что получится у меня.
SK> #include <boost\shared_array.hpp>
SK> class Mass
SK> {
SK> public:
SK> typedef boost::shared_array<int> array_t;
SK> Mass ( int N, array_t const & a )
SK> {
SK> setMass( N, a ); // не нужно ли проверить результат?
SK> }
SK> Mass ( Mass const& t )
SK> :n( t.n )
а что это за синтаксис7 Какое ключевое слово копнуть для просвещения :)
SK> ,a( t.a )
что-то тоже мне не понятное...
SK> {
SK> }
SK> Mass& operator= ( Mass const& t )
SK> {
SK> n = t.n;
SK> a = t.a;
SK> z++; // ???
SK> return *this;
SK> }
SK> bool setMass( int N, array_t const& a );
SK> private:
SK> int n;
SK> array_t a;
SK> };
SK> Cheers,
SK> Serge
SK> --- ifmail v.2.15dev5.3
SK> * Origin: Demos online service (2:5020/400)
Once (Wednesday November 01 2006) at 21:33 someone named Dmitri Roschin wrote
to Arseniy Chaplinskiy. So, look here:
AC>> Мне необходимо использовать поверхностное копирование с целью
AC>> экономии
AC>> памяти (массив может быть огромным).
AC>> Как разрешается подобное, подскажите, пожалуйста.
DR> Можно использовать подсчёт ссылок. Hапример, вместо int * a
DR> использовать refptr * pa.
DR> struct refptr
DR> {
DR> int count;
DR> int * a;
DR> };
DR> При копировании делать ++(pa->count). В деструкторе --(pa->count), и
DR> если он равен 0, убивать pa->a и pa.
Спасибо! Запускаю VS реализовывать высказанное...
DR> With best regards, Dmitri Roschin.
DR> --- ifmail v.2.15dev5.3
DR> * Origin: Demos online service (2:5020/400)
01 Hоя 06 19:30, Arseniy Chaplinskiy закинул письмецо для All:
AC> Помогите пожалуйста советом.
Как вариант после delete присвоить указателю NULL. delete(NULL) спокойно
работает.
Hу будете у нас в 5055...
mike_girkin[thedog]mail[thedot]ru
... quod erat demonstrandum - что и требовалось доказать
> >> Mass *m2;
> >> Mass *m1 = new Mass(10, a);
> >> m2 = m1 = m2;
> >> все работает, только при завершении программа падает. Из отладки
> >> выяснилось,
> >> что это результат поверхностного копирования - в классе используется
>
> SK> весьма странно, что получен именно такой результат,
> SK> B приведенном коде инициализирется указатель m1, потом
> SK> ему присваивается значение (неинициализированного, или
> SK> инициализированного нулем) указателя m1, и созданный
> SK> объект просто теряется.
> SK> Оператор Mass& Mass::operator=
> SK> в данном случае не вызывается.
> А в каком случае это происходит 7
Mass& Mass::operator= вызывается при присваивании
_объектов_ типа Mass, а в коде приведенном выше
идет присваивание _указателей_
> SK> Даже если это присваивание не приводит к undefined behaviur,
> SK> то любые попытки работать с объектами через указатели m1 и
> SK> m2 скорее всего приведут к проблемам.
> В том то и соль, что программа падает, когда вызываются деструкторы
> экземпляров. Причем по переменным m2 и m1 удается работать ...
возможно, что реальный код отличается от того что ты привел в письме
[...]
> SK> Mass ( Mass const& t )
> SK> :n( t.n )
> а что это за синтаксис7 Какое ключевое слово копнуть для просвещения :)
список инициализации членов класса
(см. например Страйструп, 3 изд. раздел 10.4.6)
Cheers,
Serge
Once (Thursday November 02 2006) at 18:45 someone named Sergiy Kanilo wrote to
Arseniy Chaplinskiy. So, look here:
>> SK> Mass ( Mass const& t )
>> SK> :n( t.n )
>> а что это за синтаксис7 Какое ключевое слово копнуть для просвещения
>> :)
SK> список инициализации членов класса
SK> (см. например Страйструп, 3 изд. раздел 10.4.6)
большое спасибо.
SK> Cheers,
SK> Serge
SK> --- ifmail v.2.15dev5.3
SK> * Origin: Demos online service (2:5020/400)