Vector prin valoare sau const referință în C++
Observă costul copierii unui vector la apelul unei funcții. Alege parametrul după intenție: citire, modificare sau copie independentă a datelor.
În acest material
O funcție care doar calculează suma unui vector nu are nevoie, de obicei, de o copie independentă a tuturor elementelor. Dacă parametrul este un vector primit prin valoare și trimiți un vector existent obișnuit, apelul construiește o copie.
Costul ascuns înaintea primei instrucțiuni
Pentru n elemente întregi, copierea vectorului are cost liniar în n și cere spațiu pentru noua secvență. Acest lucru se întâmplă înainte ca instrucțiunile din corpul funcției să înceapă prelucrarea. Analiza timpului trebuie să includă și pregătirea parametrilor.
Dacă apelezi o funcție de n ori și la fiecare apel copiezi un vector de n elemente, doar copiile pot costa pătratic. Un corp al funcției care pare să facă o singură comparație nu face întregul apel constant.
Alege după contractul funcției
Un parametru const std::vector<int>& permite citirea vectorului existent fără copierea elementelor la apel. const exprimă faptul că funcția nu modifică vectorul prin acea referință. Un parametru std::vector<int>& permite modificarea obiectului apelantului.
Primirea prin valoare este potrivită când funcția are nevoie intenționat de o copie pe care să o transforme independent sau când interfața urmărește preluarea unei valori. Nu este o greșeală universală; devine o problemă când costul și efectele nu corespund intenției.
Un vector existent cu n elemente transmis prin valoare la fiecare dintre n apeluri poate produce n×n copii de elemente. Referința const evită această copie pentru citire.Mărește schema ↗
Tabloul clasic are alt comportament
Un parametru obișnuit scris int a[] este ajustat la un pointer. Nu copiază automat toate elementele tabloului. Dimensiunea logică trebuie transmisă separat, iar modificările elementelor pot fi vizibile apelantului.
Pentru citire, un parametru cu elemente const exprimă protecția datelor. Această diferență explică de ce schimbarea reprezentării din tablou clasic în vector cere și verificarea semnăturilor funcțiilor, nu doar înlocuirea declarației din main.
Verifică efectele, apoi performanța
Scrie înainte de apel dacă vectorul trebuie să rămână identic. După apel, compară datele și verifică rezultatul calculat. Separat, analizează câte elemente sunt copiate și de câte ori este apelată funcția.
Nu presupune că toate apelurile prin valoare fac aceeași copie: mutarea și eliminarea unor copii au reguli distincte. Pentru cazul didactic al unui vector existent transmis unei funcții de citire, referința const exprimă clar intenția și evită copia elementelor.
Revezi parametrii funcțiilor, vectorul STL și complexitatea.
Întrebări frecvente
Ce cost are transmiterea unui vector prin valoare?
La transmiterea unui vector existent obișnuit se construiește o copie. Pentru n elemente întregi, aceasta implică timp O(n) și memorie pentru copia elementelor, înaintea corpului funcției.
Când folosesc const vector<int>& ca parametru?
Când funcția trebuie să citească vectorul existent fără să îl copieze și fără să îi modifice elementele prin acel parametru. Referința păstrează accesul la obiectul apelantului.
Ce parametru folosesc dacă funcția trebuie să modifice vectorul apelantului?
O referință neconstantă, precum vector<int>&, exprimă această intenție. Transmiterea prin valoare modifică doar copia locală, dacă nu există alte mecanisme explicite de întoarcere a rezultatului.