Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Копирование экземпляра

2 views
Skip to first unread message

Arseniy Chaplinskiy

unread,
Nov 1, 2006, 11:30:44 AM11/1/06
to
Hello, All !

Спроектирвал класс:

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

Sergiy Kanilo

unread,
Nov 1, 2006, 12:58:25 PM11/1/06
to
"Arseniy Chaplinskiy" <Arseniy.C...@p696.f1532.n5030.z2.fidonet.org>
wrote in message news:11623...@p696.f1532.n5030.z2.ftn...

> 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


Dmitri Roschin

unread,
Nov 1, 2006, 1:33:40 PM11/1/06
to
Hello, Arseniy!
You wrote to All on Wed, 01 Nov 2006 19:30:44 +0300:

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.


Arseniy Chaplinskiy

unread,
Nov 2, 2006, 1:33:30 AM11/2/06
to
Hello, Sergiy !

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)

Arseniy Chaplinskiy

unread,
Nov 2, 2006, 1:34:24 AM11/2/06
to
Hello, Dmitri !

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)

Mike Girkin

unread,
Nov 1, 2006, 4:25:14 PM11/1/06
to

Приветствую, Arseniy !

01 Hоя 06 19:30, Arseniy Chaplinskiy закинул письмецо для All:

AC> Помогите пожалуйста советом.
Как вариант после delete присвоить указателю NULL. delete(NULL) спокойно
работает.

Hу будете у нас в 5055...
mike_girkin[thedog]mail[thedot]ru

... quod erat demonstrandum - что и требовалось доказать

Sergiy Kanilo

unread,
Nov 2, 2006, 10:45:55 AM11/2/06
to
"Arseniy Chaplinskiy" <Arseniy.C...@p696.f1532.n5030.z2.fidonet.org>
wrote in message news:11624...@p696.f1532.n5030.z2.ftn...

> >> 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


Arseniy Chaplinskiy

unread,
Nov 3, 2006, 4:57:04 PM11/3/06
to
Hello, Sergiy !

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)

0 new messages