usuario6426033
Tome el siguiente código:
std::vector<int> a;
a.reserve(65536);
std::vector<int> b(a); //NOTE: b is constructed from a
a.reserve(65536); // no reallocation
b.reserve(65536);
¿Se copia la capacidad? ¿Habrá una reasignación en la última línea? ¿La norma dice algo al respecto o es silenciosa?
uh oh alguien necesita un cachorro
¿Se copia la capacidad?
En la práctica, no. Lo probé en línea en Clang y GCC tanto como MSVC y ninguno de ellos copia la capacidad.
¿Habrá una reasignación en la última línea?
Si la capacidad es menor que el argumento para reservar (es decir, no se copia), entonces sí.
¿La norma dice algo al respecto o es silenciosa?
No se proporcionan definiciones para el constructor de copia en vector.contras. En su lugar, tenemos que mirar el contenedor.requisitos
X
denota una clase de contenedor que contiene objetos de tipoT
,a
y
b
denotan valores de tipoX
,u
denota un identificador,r
denota un valor no constante de tipoX
yrv
denota un valor r no constante de tipoX
.
X u(a)
X u = a;
Requiere:
T
esCopyInsertable
dentroX
(vea abajo).correo:
u == a
Ahora, ¿qué significa que dos contenedores sean iguales?
a == b
==
es una relación de equivalencia.equal(a.begin(), a.end(), b.begin(), b.end())
En otras palabras, dado que no requiere capacity
ser iguales en la comparación, entonces no hay razón para copiar el capacity
.
-
@P0W No hay una manera fácil que pueda ver para vincular a una muestra de código directo en rextester.
– uh oh alguien necesita un cachorro
6 de junio de 2016 a las 4:27
AnatolyS
El estándar no dice nada sobre la preservación de la capacidad cuando llama al constructor de copias. Así que no tienes ninguna garantía al respecto.
Pero puede hacer el siguiente truco, que intercambia el estado de a y b, si necesita conservar la capacidad solo en la copia:
std::vector<int> a;
a.reserve(65536);
std::vector<int> b(a);
b.swap(a); // now b has a's state
assert(b.capacity() == 65536);
-
esto solo cambia cual
reserve
la llamada provocará una reasignación.– Saludos y hth. – alf
5 de junio de 2016 a las 8:42
-
swap no hace nada con el asignador, intercambia solo el estado de los objetos.
– AnatolyS
5 de junio de 2016 a las 10:05
-
Entonces, ¿puedes intercambiar vectores que tengan diferentes asignadores? Si es así, no puede simplemente intercambiar la parte única de la memoria asignada.
– JDługosz
5 de junio de 2016 a las 10:22
-
@JDługosz Dos vectores con diferentes tipos de asignador son tipos de vectores diferentes, por lo que no puede intercambiarlos.
– AnatolyS
5 de junio de 2016 a las 10:36
-
@AnatolyS Esto no es cierto en C++ 11. En C ++ 03, los asignadores debían ser sin estado, por lo que la declaración “el intercambio no hace nada con los asignadores” es algo cierta. En C++11 el comportamiento de
swap
con respecto al asignador está personalizado porallocator_traits<Alloc>::propagate_on_container_swap
.– sbabbi
5 de junio de 2016 a las 12:10
Saludos y hth. – alf
No, no se garantiza que la capacidad sea preservada por un vector
copiar la construcción.
Puedes hacerlo de la siguiente manera:
vector<int> b;
b.reserve( a.capacity() );
b = a;
Mejor encapsulado en una función.
Eisa N.
Bueno, una simple verificación como la siguiente revela que la capacidad no se copia:
std::vector<int> a;
a.reserve(65536);
cout << "a.capacity is " << a.capacity() << endl; // prints 65536
std::vector<int> b(a); //NOTE: b is constructed from a
cout << "b.capacity is " << b.capacity() << endl; // prints 0
Creo que al copiar el vector a
a b
la capacidad de b
se ajusta al tamaño de a
en la mayoría de los compiladores; aunque esto no está garantizado.
terry
- Como se muestra a continuación en el código fuente del vector SGI STL, operador= reservará espacio para exactamente norte elementos, es decir _M_fin_de_almacenamiento = _M_inicio + __xlen;.
template <class _Tp, class _Alloc>
vector<_Tp,_Alloc>&
vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x)
{
if (&__x != this) {
const size_type __xlen = __x.size();
if (__xlen > capacity()) {
iterator __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
_M_end_of_storage = _M_start + __xlen;
}
else if (size() >= __xlen) {
iterator __i = copy(__x.begin(), __x.end(), begin());
destroy(__i, _M_finish);
}
else {
copy(__x.begin(), __x.begin() + size(), _M_start);
uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
}
_M_finish = _M_start + __xlen;
}
return *this;
}
- Como se muestra a continuación en el código fuente del vector SGI STL, los vectores copiar constructor reservará espacio para exactamente norte elementos, es decir _M_fin_de_almacenamiento = _M_inicio + __n;.
template <class _InputIterator>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type()) : _Base(__a) {
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_initialize_aux(__first, __last, _Integral());
}
template <class _Integer>
void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) {
_M_start = _M_allocate(__n);
_M_end_of_storage = _M_start + __n;
_M_finish = uninitialized_fill_n(_M_start, __n, __value);
}
En la documentación de vector c-tors, se afirma que copia elementos. es.cppreference.com/w/cpp/container/vector/vector
– paweldac
5 de junio de 2016 a las 7:26
Posible duplicado de la capacidad std::vector después de copiar
– jww
14 de octubre de 2018 a las 3:09