Domanda

Se ho una lezione che ne ha molti int, float, e enum Variabili membri, è considerato efficiente e/o buona pratica restituirle come riferimenti piuttosto che copie e restituire riferimenti costanti in cui non dovrebbero essere apportate modifiche? O c'è un motivo per cui dovrei restituirli come copie?

È stato utile?

Soluzione

Non c'è motivo di restituire tipi primitivi come int e float Per riferimento, a meno che tu non voglia consentire loro di essere cambiati. Restituirli con riferimento è in realtà meno efficiente perché non risparmia nulla (intS e i puntatori hanno di solito le stesse dimensioni) mentre la dereferenziazione aggiunge effettivamente sovraccarico.

Altri suggerimenti

Se sono riferimenti costanti, forse va bene. Se non sono riferimenti costanti, probabilmente no.

Per quanto riguarda l'efficienza-su una macchina a 64 bit, i riferimenti saranno quantità a 64 bit (puntatori sotto mentite spoglie); int e float e enum sarà più piccolo. Se restituisci un riferimento, stai forzando un livello di indirezione; è meno efficiente.

Pertanto, specialmente per i tipi integrati come valori di ritorno, è generalmente meglio restituire il valore anziché un riferimento.

In alcuni casi è necessario:

Guarda il sovraccarico operator[] per qualsiasi classe. Di solito ha due versioni. La versione mutante deve restituire un riferimento.

int &operator[](int index);           // by reference
int operator[](int index) const;      // by value

In generale, è OK consentire l'accesso ai membri della classe da parte di entità affidabili da parte di una classe, ad esempio amici. Nel caso in cui queste entità fidate debbano anche modificare lo stato, i riferimenti o i puntatori ai membri della classe, sono le uniche opzioni che uno ha.

In molti casi, i riferimenti di solito semplificano la sintassi, ad esempio dove "V" è vettore STL.

v.at(1) = 2 vs *(v.at(1)) = 2;

Questa è probabilmente principalmente una questione di stile o preferenza. Uno dei motivi per non restituire i riferimenti è perché si utilizzano getter e setter per consentirti di modificare l'implementazione di tali membri, se hai cambiato un membro privato in un altro tipo o se lo hai rimosso completamente perché può essere calcolato, allora non hai più La capacità di restituire un riferimento, poiché non c'è nulla da fare riferimento.

D'altra parte, i riferimenti di ritorno per tipi non banali (classi composti) possono accelerare un po 'il codice facendo una copia e puoi consentire l'assegnazione di tali membri tramite il riferimento restituito (se desiderato).

Quasi, i riferimenti const sono migliori. Per INT e tali non hanno senso perché vorresti che fossero cambiati o perché hanno le stesse dimensioni (o quasi) come riferimento.

Quindi sì, è una buona idea. Preferisco un'altra lingua o per hackerare le mie cose C ++ e permettere al VAR di essere pubblico (ancora una volta è solo le mie cose)

Questa è una domanda per le prestazioni principalmente, ma da un punto di vista della robustezza direi che è preferibilmente restituire valori invece di const riferimenti. Il motivo è che persino i riferimenti a const indeboliscono l'incapsulamento. Considera questo:

struct SomeClass
{
   std::vector<int> const & SomeInts () const;
   void AddAnInt (int i);  // Adds an integer to the vector of ints.
private:
   std::vector<int> m_someInts;
};

bool ShouldIAddThisInt(int i);

void F (SomeClass & sc)
{
   auto someInts = sc.SomeInts ();
   auto end = someInts.end ();
   for (auto iter = someInts.begin (); iter != end; ++iter)
   {
      if (ShouldIAddThisInt(*iter))
      {
         // oops invalidates the iterators
         sc.AddAnInt (*iter);
      }
   }  
}

Quindi, nel caso in cui abbia senso semanticamente e possiamo evitare allocazioni dinamiche eccessive, preferisco il ritorno in base al valore.

I getter sono per le emissioni di una classe dicono Exhaust Car.emit(), dove l'auto ha appena creato il Exhaust.

Se sei tenuto a scrivere const Seat& Car.get_front_seat()
in seguito seduto nel Driver, puoi notare immediatamente che qualcosa non va.
Correttamente, preferiresti scrivere Car.get_in_driver(Driver)
che quindi chiama direttamente seat.sit_into(Driver).

Questo secondo metodo evita facilmente quelle situazioni imbarazzanti quando tu get_front_seat Ma la porta è chiusa e si spinge praticamente il conducente attraverso la porta chiusa. Ricorda, hai chiesto solo un posto! :)

Tutto sommato: restituire sempre per valore (e fare affidamento sull'ottimizzazione del valore di ritorno) o rendersi conto che è tempo di modificare il tuo design.

Lo sfondo: le classi sono state create in modo che i dati possano essere accoppiati insieme alla sua funzionalità degli accessori, localizzare i bug ecc. Pertanto le classi non sono mai attività, ma orientate ai dati.

Ulteriori insidie: In C ++ Se restituisci qualcosa per const Ref, puoi facilmente dimenticare che è solo un ref e una volta che il tuo oggetto è distrutto puoi essere lasciato con un riferimento non valido. Altrimenti, quell'oggetto sarà copiato Una volta lascia il getter comunque. Ma il compilatore si evita di copie inutili Restituire l'ottimizzazione del valore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top