конструктор копирования...
От: atrofa Украина  
Дата: 22.09.04 11:42
Оценка:
Привет всем

Есть у меня такие структуры:

typedef struct RespVisit
{
CString sVisitID;
long lNumDocument;
RespDocument* pDocuments;
} RespVisit;

typedef struct RespPatient
{
CString sMRN;
long lNumVisit;
RespVisit* pVisits;
} RespPatient;

typedef struct ResponseData
{
CString siteID;
CString doctorID;
long lNumPatient;
RespPatient* pPatients;
} ResponseData;

есть переменная
ResponseData respData;

RespPatient* respPat = new RespPatient [2];
// запонляем структуру

respData.lNumPatient = 2;
respData.pPatients = respPat;

delete [] respPat;
//respData.pPatients — при образещии error

как написать коструктор копирования что после удаления памяти для respPat, в respData.pPatients оставались данные?

Спасибо
Re: конструктор копирования...
От: Shhady Россия  
Дата: 22.09.04 11:57
Оценка:
Здравствуйте, atrofa, Вы писали:

A>как написать коструктор копирования что после удаления памяти для respPat, в respData.pPatients оставались данные?


Какой такой "конструктор копирования" ? Что ты подразумеваешь под ним? Я обычно когда объекты копируются. Ты тут присваиваешь указатели а не объекты друг другу (скажи честно, код твой? так как у тебя даже стоит p перед указателями). Тебе не надо удалять массив respPat, так как ты удаляешь объекты из хипа,указатели на которые хранятся в ResponseData. Тебе надо:
1) Либо хранить не указатели, а сами объекты RespPatient в ResponseData (так сказать "по значению"), тогда юзая vector, соотвественно нужен конструктор копирования
2) Либо не делать delete [] respPat, а удалять respPat в деструкторе ResponseData.
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re: конструктор копирования...
От: PM  
Дата: 22.09.04 11:58
Оценка:
Здраствуйте, atrofa, Вы писали:

a> Привет всем


a> Есть у меня такие структуры:

[классы поскипаны]

a> есть переменная

a> ResponseData respData;

a> RespPatient* respPat = new RespPatient [2];

a> respData.lNumPatient = 2;
a> respData.pPatients = respPat;
a> delete [] respPat;
a> //respData.pPatients
a> — при образещии error

Еще бы не было ошибки — ведь после respData.pPatients = respPat; respPat и respData.pPatients указывают на одну область памяти, которая в следующей строке освобождается и respData.pPatients начинает указывать неизвестно на что.

a> как написать коструктор копирования что после

a> удаления памяти для
a> respPat, в respData.pPatients оставались данные?
Примерно так:
#include <vector>

struct RespVisit
{
    CString sVisitID;
    std::vector<RespDocument> Documents;
};

struct RespPatient
{
    CString sMRN;
    std::vector<RespVisit> Visits;
};

struct ResponseData
{
    CString siteID;
    CString doctorID;
    std::vector<RespPatient> Patients;
};

ResponseData respData;
respData.Patients.resize(2); // задаем размер вектора равный 2 элементам
foobar2000 v0.8.3: Koop — Waltz For Koop (Feat Cecilia Stalin) [Waltz For Koop (JCR021)]
Re: конструктор копирования...
От: Аноним  
Дата: 22.09.04 12:10
Оценка:
Открытые члены данных типа указатель на что-то — плохая идея.
Первый глюк ты уже поймал.
Еще может возникнуть утечка ресурсов или удалишь что-нибудь более одного раза.
Re[2]: конструктор копирования...
От: atrofa Украина  
Дата: 22.09.04 12:25
Оценка:
Здравствуйте, Shhady, Вы писали:

S>Здравствуйте, atrofa, Вы писали:


A>>как написать коструктор копирования что после удаления памяти для respPat, в respData.pPatients оставались данные?


S>Какой такой "конструктор копирования" ? Что ты подразумеваешь под ним? Я обычно когда объекты копируются. Ты тут присваиваешь указатели а не объекты друг другу (скажи честно, код твой? так как у тебя даже стоит p перед указателями). Тебе не надо удалять массив respPat, так как ты удаляешь объекты из хипа,указатели на которые хранятся в ResponseData. Тебе надо:

S>1) Либо хранить не указатели, а сами объекты RespPatient в ResponseData (так сказать "по значению"), тогда юзая vector, соотвественно нужен конструктор копирования
S>2) Либо не делать delete [] respPat, а удалять respPat в деструкторе ResponseData.


код конечно мой..

да я понимаю что происходит, что указатели указывают на один участок памяти..
но как сделать что бю при такой записи, копировались не указатели а занчения.. зделать конструктор копирования для массива что ли? что б не было опасности что после удаления respPat все рухнет
Re[3]: конструктор копирования...
От: Shhady Россия  
Дата: 22.09.04 12:34
Оценка:
Здравствуйте, atrofa, Вы писали:

A>код конечно мой..

твой так твой

A>да я понимаю что происходит, что указатели указывают на один участок памяти..

A>но как сделать что бю при такой записи, копировались не указатели а занчения.. зделать конструктор копирования для массива что ли? что б не было опасности что после удаления respPat все рухнет
стандартными способами никак, не существует в c++ "конструктор копирования для массива".
Я никак не пойму, если хочешь, чтоб копировались значения, храни по значениям, нафига тебе new нужен или ты не понимаешь чего-то? спрашивай, ответим
... << RSDN@Home 1.1.3 stable >>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[4]: конструктор копирования...
От: atrofa Украина  
Дата: 23.09.04 05:40
Оценка:
Здравствуйте, Shhady, Вы писали:

S>Здравствуйте, atrofa, Вы писали:


A>>код конечно мой..

S>твой так твой

A>>да я понимаю что происходит, что указатели указывают на один участок памяти..

A>>но как сделать что бю при такой записи, копировались не указатели а занчения.. зделать конструктор копирования для массива что ли? что б не было опасности что после удаления respPat все рухнет
S>стандартными способами никак, не существует в c++ "конструктор копирования для массива".
S>Я никак не пойму, если хочешь, чтоб копировались значения, храни по значениям, нафига тебе new нужен или ты не понимаешь чего-то? спрашивай, ответим

у меня в класе есть указатель на массив, так вот при присвоении нужно ж под него память выделять??
сейчас сделал так:


class CRespPatient
{
...
};

class CResponseData
{
public:
....
void SetPatients(CRespPatient* pInfo, long lNumInfo);

private:
  CRespPatient* pPatients;
  long lNumPatient;
};

void CResponseData::SetPatients(CRespPatient* pInfo, long lNumInfo)
{
    if ( lNumPatient ) delete [] pPatients;
    if( lNumInfo > 0)
    {
        lNumPatient = lNumInfo;
        pPatients = new CRespPatient[lNumPatient];
        for( int i = 0; i < lNumPatient; i++)
        {
            pPatients[i] = pInfo[i];
        }
    }
}


можно еще зделать со smart-указателями, но на это нет времени..
Есть какой то другой способ?
Re[5]: конструктор копирования...
От: Shhady Россия  
Дата: 23.09.04 07:30
Оценка:
Здравствуйте, atrofa, Вы писали:

A>у меня в класе есть указатель на массив, так вот при присвоении нужно ж под него память выделять??

A>сейчас сделал так:
Смотря что ты хочешь сделать. Если хочешь хранить в указатели копию, то да. Если же хочешь хранить просто указатель, то нет.

A>
A>class CRespPatient
A>{
A>...
A>};

A>class CResponseData
A>{
A>public:
A>....
A>void SetPatients(CRespPatient* pInfo, long lNumInfo);

A>private:
A>  CRespPatient* pPatients;
A>  long lNumPatient;
A>};

A>void CResponseData::SetPatients(CRespPatient* pInfo, long lNumInfo)
A>{
A>    if ( lNumPatient ) delete [] pPatients;
A>    if( lNumInfo > 0)
A>    {
A>        lNumPatient = lNumInfo;
A>        pPatients = new CRespPatient[lNumPatient];
A>        for( int i = 0; i < lNumPatient; i++)
A>        {
A>            *pPatients[i] = *pInfo[i];            // тут
A>        }
A>    }
A>}
A>


A>можно еще зделать со smart-указателями, но на это нет времени..

A>Есть какой то другой способ?
Есть Надо поправить глюки.
*pPatients[i] = *pInfo[i];

В первоночальном варианте ты просто присваивал указатель pPatients на pInfo (а pPatioents уже указавыл на память, которую ты двумя строчками выше выделял, соответственно происходит утечка памяти
да еще куча глюков, если pInfo была в вызывающей функции в стеке, то у тебя программа может очень весело себя вести да и много других багов ты одной строкой схватил ), а тебе надо копировать
один объект в другой (ты не разыменовал указатель). И еще тебе надо сделать опреатор копирования, поскольку если ты его не сделаешь в CRespPatient, то компилятор проглотит копирование, но он скопирует побитно, ладно, долго объеснять, сделай оператор копирования и присвваивания в CRespPatient чтоб не глючило, а еще лучше, использую std::vector
... << RSDN@Home 1.1.3 stable >>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.