c++ - varias - formula para copiar datos de una celda a otra en excel
¿Hay una manera estándar de mover un rango en un vector? (2)
Considere el siguiente programa que inserta un rango de elementos en un vector:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
v1.insert(v1.end(), v2.begin(), v2.end());
Esto copia de manera eficiente el rango, asignando suficiente espacio en el vector objetivo para todo el rango, de modo que se requerirá un máximo de un cambio de tamaño. Ahora considere el siguiente programa que intenta mover un rango a un vector:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
for_each ( v2.begin(), v2.end(), [&v1]( string & s )
{
v1.emplace_back(std::move(s));
});
Esto realiza un movimiento exitoso pero no disfruta de los beneficios que tiene insert () con respecto a la preasignación del espacio en el vector objetivo, por lo que el vector podría redimensionarse varias veces durante la operación.
Entonces, mi pregunta es, ¿existe un inserto equivalente que pueda mover un rango a un vector?
std::move
algorithm with preallocation:#include <iterator> #include <algorithm> v1.reserve(v1.size() + v2.size()); // optional std::move(v2.begin(), v2.end(), std::back_inserter(v1));
Lo siguiente sería más flexible aún:
v1.insert(v1.end(), std::make_move_iterator(v2.begin()), std::make_move_iterator(v2.end()));
Steve Jessop proporcionó información de fondo sobre qué hace exactamente y, probablemente, cómo lo hace.
Utiliza un move_iterator
con insert
:
v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end()));
El ejemplo en 24.5.3 es casi exactamente esto.
Obtendrá la optimización que desea si (a) vector::insert
utiliza el envío iterator-tag para detectar el iterador de acceso aleatorio y precalcular el tamaño (que asumió que en su ejemplo que copia), y (b ) move_iterator
conserva la categoría de iterador del iterador que envuelve (que es requerido por el estándar).
En un punto oscuro: estoy bastante seguro de que vector::insert
puede emplazar desde el origen (lo cual es irrelevante aquí, ya que el origen es del mismo tipo que el destino, por lo que un emplace es lo mismo que copiar / mover, pero sería relevante para ejemplos de lo contrario idénticos). Todavía no he encontrado una declaración de que sea necesario hacerlo, simplemente lo deduje del hecho de que el requisito en el par de iteradores i,j
pasado para insert
es que T
debe ser EmplaceConstructible
de *i
.