Questo sembra essere un difetto di progettazione, è stato risolto ora.
Lo standard C++ 98 specifica che una funzione membro solo dei contenitori passa il suo parametro (T) per valore invece che per riferimento const:
vuoto ridimensionamento (size_type sz, T c = T());
Questo fatto è stato discusso/discusso ripetutamente nel corso degli anni, la prima volta anche prima che il C++ 98 fosse ratificato. Il razionale per il passaggio di questo parametro per valore è stato:
Così che l'auto fa riferimento a dichiarazioni sono garantiti per lavoro, per esempio:
v.resize(v.size() + 1, v[0]);
Tuttavia questa logica non è convincente come la firma per push_back è:
void push_back(const T& x);
E push_back ha una semantica simile da ridimensionare (append). E push_back deve funzionare anche in caso di auto riferimento:
v.push_back(v[0]); // must work
Il problema con il passaggio per valore T è che può essere significativamente più costoso di passaggio per riferimento. L'opposto è anche vero, tuttavia quando è vero è di solito molto meno drammatico (ad esempio per i tipi scalari).
Anche con la semantica del movimento disponibile, il passaggio di questo parametro in base al valore può essere costoso.Si consideri per esempio vector>:
std::vector<int> x(1000);
std::vector<std::vector<int>> v;
...
v.resize(v.size()+1, x);
Nel caso passaggio per valore, x viene copiato volta al parametro di ridimensionamento. E poi internamente, dato che il codice non può sapere in fase di compilazione di quanto ridimensiona il vettore, il x viene solitamente copiato (non spostato) una seconda volta dal parametro di ridimensionamento nella sua posizione corretta all'interno del vettore.
Con pass-by-const riferimento, il x nell'esempio precedente deve essere copiato solo una volta. In questo caso, x ha un costoso costruttore di copie e quindi qualsiasi copia che può essere salvata rappresenta un risparmio significativo.
Se siamo in grado di essere efficienti per push_back, dovremmo essere efficiente per il ridimensionamento pure. Il ridimensionamento che prende un parametro di riferimento è stato codificato e spedito nella libreria CodeWarrior senza segnalazioni di problemi di cui sono a conoscenza.
Proposta di delibera:
Change 23.3.3 [deque], p2:
class deque {
...
void resize(size_type sz, const T& c);
Change 23.3.3.3 [deque.capacity], p3:
void resize(size_type sz, const T& c);
Change 23.3. 5 [lista], p2:
class list {
...
void resize(size_type sz, const T& c);
Ch ange 23.3.5.3 [list.capacity], p3:
void resize(size_type sz, const T& c);
Change 23.3.6 [vettore], p2:
class vector {
...
void resize(size_type sz, const T& c);
Change 23.3.6.3 [vector.capacity], p11:
void resize(size_type sz, const T& c);
@ user814628 Questo non mi sembra giusto. L'unica volta che 'value_type val = value_type()' potrebbe non funzionare è se 'value_type' ha un costruttore di copie che ha preso un riferimento non const. –
Non avevo mai notato prima che anche * fosse * un secondo parametro da ridimensionare (...)! Credo di aver imparato la mia unica cosa per il giorno e ora posso andare avanti fino a domani. :-P – aldo