PDA

Visualizza la versione completa : [c++]puntatori e funzioni


giuseppe500
21-08-2008, 18:10
ciao.
E' un po che programmo in c++ e un po che ho questo dubbio:

quando voglio farmi restituire un oggetto da una funzione faccio cosi:


void classe::myFunc(&oggetto);
e nella dichiarazione:
void myFunc(oggetto * obj){implementazione};


il casino è questo:

se instanzio un oggetto


oggetto * pOggetto = new oggetto();


e poi ad es all'interno di un ciclo chiamo la mia funzione passando quell'oggetto:
ed inserisco il tutto in un array.


oggetto * pOggetto = new oggetto();

while(indice<MAXINDICE)
{
myFunc(&pOggetto);
myArray.add(pOggetto);
}


alla fine mi ritrovo un array con tutti gli oggetti uguali , è giusto?
perchè passo il riferimento dell'oggetto all'array, ma il riferimento è lo stesso , perchè dichiaro lo dichiaro una sola volta fuori dal ciclo.

come faccio ad avere un array con gli oggetti giusti?ossia passando all'array il valore dell'oggetto e non il riferimento all'oggetto?

Il tutto stà secondo me nella posizione dove si dichiara l'oggetto:
tipo , questo è un approccio giusto ?



while(indice<MAXINDICE)
{
oggetto * pOggetto = new oggetto();

myFunc(&pOggetto);
myArray.add(pOggetto);
}


o è meglio fare in altir modi?
voi cosa mi consigliate ?perchè ,mi viene il dubbio ad es di dichiarare il puntatore all' interno della funzione che chiamo ,ma non so se poi all' uscita è valido!!
grazie.

shodan
21-08-2008, 19:33
Ma che dovrebbe fare questa fantomatica myFunc?

menphisx
22-08-2008, 01:30
Ma perchè passi l'indirizzo di un puntatore, invece del puntatore stesso ?


oggetto * pOggetto = new oggetto();

while(indice<MAXINDICE)
{
myFunc(&pOggetto);
myArray.add(pOggetto);
}


:ciauz:

giuseppe500
22-08-2008, 10:39
Originariamente inviato da shodan
Ma che dovrebbe fare questa fantomatica myFunc?

la funzione myFunc dovrebbe "riempire" con dei dati l'oggetto pOggetto.
ad es prendendoli da un db o da qualsiasi altra sorgente dati

Il problema è che non so dove fare il new di poggetto , fuori o dentro la funzione myFUnc per far si che nell' array siano aggiunti puntatori diversi e non sempre lo stesso riscritto perchè passato per riferimento.
Grazie

shodan
22-08-2008, 12:49
L'ho chiesto perché tempo fa mi sembrava di aver visto una imprecisione.
Comunque (in teoria) l'approccio corretto è questo, (incompleto comunque: l'incremento di indice dov'è?) visto che a ogni ciclo devi allocare un oggetto.
Pero:
la & va tolta come detto da menphisx e il prototipo void myFunc(oggetto* obj){implementazione}; deve diventare void myFunc(oggetto*& obj){implementazione};
Così passi un reference al puntatore.


while(indice<MAXINDICE)
{
oggetto * pOggetto = new oggetto();
myFunc(pOggetto);
myArray.add(pOggetto);
}

Personalmente modificherei il codice in questo modo:


while(indice<MAXINDICE)
{
oggetto* pOggetto = myFunc();
myArray.add(pOggetto);
indice++;
}

In pratica sposterei l'allocazione all'interno della funzione myFunc (e considererei l'uso di smart_pointer in caso la new sollevasse un'eccezione).

P.S.
L'ultimo passo potrebbe essere non necessario se myFunc è intelligente. Ad esempio.


oggetto* myFunc() {
try {
oggetto* mObj = new oggetto();
// cose varie da fare
return mObj;
} catch (std::bad_alloc&) {
return 0; // o NULL (stessa cosa)
}
return 0; // o NULL (stessa cosa) qui per evitare un eventuale warnig del compilatore.
}

giuseppe500
22-08-2008, 13:45
grazie .
posto un po di codice perch ho un problema di delete:


while(!m_pData->m_BeamLoadsIterator->ISEof()) {
tagLoadData* pLoadData = new tagLoadData();
//Flag per sapere se B prec. coincide con A corrente
bool bAB = ((LDTemp.dDistA == LDOld.dDistB) && (LDTemp.dValOverLA == LDOld.dValOverLB)
|| TagsLoadData.IsEmpty());//Sempre true la prima volta

//se punto B prec. è diverso dal Punto A aggiungo anche B precedente
if (!bAB && !TagsLoadData.IsEmpty()){
m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDOld, false, false);
TagsLoadData.Add(pLoadData);

bNew = true;
}
//aggiungo sempre il punto A
m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDTemp, bNew, true);
TagsLoadData.Add(pLoadData);
pLoadData = new tagLoadData();
bNew = false;

LDOld = LDTemp;
m_pData->m_BeamLoadsIterator->MoveNext();
if(!m_pData->m_BeamLoadsIterator->ISEof())
m_pData->m_BeamLoadsIterator->LoadTagLoadsTemp(&LDTemp);
if(!CompareLDTemp(&LDTemp, &LDOld) ||m_pData->m_BeamLoadsIterator->ISEof()){
//se cambia qualcosa o sono alla fine aggiungo sempre il punto B finale,
//aggiungo al DomainModel e vado avanti
m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDOld, false, false);
TagsLoadData.Add(pLoadData);
nTypeLoad = m_pData->m_BeamLoadsIterator->GetTypeLoad(LOAD_DISTR, LDOld.strCoordSys, LDOld.strType);

InsInDomainModel(&LDOld, &TagsLoadData, nTypeLoad);

bNew = true;
}
}




questa è la mia myfunc:


m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDTemp, bNew, true);

e pLoadData è il mio pObject.

il problema è che all'esterno della mia classe viene fatto il delete di tutti i contenuti dell'array TagsLoadData.
ho 2 allocazioni di pObject(pLoadData) perchè devoaggiungere 2 volte nello stesso ciclo.
In questo modo mi escono dei memory leaks,probabilmente penso per la riallocazione di pObject.
Puo essere?
grazie.
ps.adesso sto riscrivendo il codice con il tuo metodo .
tu come risolveresti?
grazie.

shodan
22-08-2008, 15:48
Il problema c'è l'hai perché aggiungi due volte lo stesso puntatore a TagsLoadData quando l'if è true (per altro sovrascrivendo i dati alla seconda chiamata di < GetLoadData > )


//se punto B prec. è diverso dal Punto A aggiungo anche B precedente
if (!bAB && !TagsLoadData.IsEmpty()){
m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDOld, false, false);
TagsLoadData.Add(pLoadData);

bNew = true;
}
//aggiungo sempre il punto A
m_pData->m_BeamLoadsIterator->GetLoadData(pLoadData,&LDTemp, bNew, true);
TagsLoadData.Add(pLoadData);

Per risolvere basta fare come ho detto prima: lasciare che sia la funzione ad allocare l'oggetto.


//se punto B prec. è diverso dal Punto A aggiungo anche B precedente
if (!bAB && !TagsLoadData.IsEmpty()){
tagLoadData* pLoadData = m_pData->m_BeamLoadsIterator->GetLoadData(&LDOld, false, false);
TagsLoadData.Add(pLoadData);

bNew = true;
}
//aggiungo sempre il punto A
tagLoadData* pLoadData= m_pData->m_BeamLoadsIterator->GetLoadData(&LDTemp, bNew, true);
TagsLoadData.Add(pLoadData);

così ogni puntatore avra una zona di memoria diversa a cui fa riferimento.

giuseppe500
22-08-2008, 16:10
scusa cavoli , non l'avevo vista la tua implementazione di myfunc

shodan
22-08-2008, 16:25
Probabilmente hai letto mentre modificavo il post.

Loading