c++ - unir - concatenar varias celdas en excel 2016
¿Controla std:: copy los rangos superpuestos? (4)
Condiciones previas para std::copy
, prohíbe una superposición:
Prototipo
template <class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
Precondiciones
[first, last)
es un rango válido.- el resultado no es un iterador dentro del rango
[first, last)
.- Hay espacio suficiente para guardar todos los elementos que se copian. Más formalmente, el requisito es que
[result, result + (last - first))
es un rango válido. std::copy
Al copiar datos de un rango a otro, debe tener cuidado si hay una superposición parcial entre los rangos de origen y destino. Si el inicio del rango de destino se superpone a la cola del rango de origen, una copia secuencial sin formato distorsionará los datos. La biblioteca de tiempo de ejecución de C tiene memmove
además de memcpy
para manejar tales problemas de superposición.
Asumo que std::copy
funciona como memcpy
, ya que no tiene en cuenta la superposición entre las regiones de origen y destino. Si intenta cambiar los objetos "hacia abajo" en un std::vector
con std::copy
, corromperá los datos. ¿Existe un algoritmo analógico STL de memmove
para manejar situaciones como esta? ¿O debería rodar mi propio con iteradores inversos?
No maneja los rangos de superposición si el inicio del rango de salida se superpone con el rango de entrada.
Afortunadamente, puede usar std::copy_backward
en std::copy_backward
lugar (lo que requiere que no se superponga el final del rango de salida con el rango de entrada).
Parece que la forma más directa sería crear un vector temporal del rango que desea copiar:
std::vector copiedRange( srcVecIterBegin, srcVecIterEnd);
std::copy( copiedRange.begin(), copiedRange.end(), srcVecIterCopyLocIter);
Puede envolver esto en una función de plantilla que debería poder hacer una superposición usando cualquier tipo de contenedor / iterador.
Borrador estándar de C ++ 17
El borrador estándar de C ++ 17 n4659 dice:
28.6.1 "Copia":
template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
1 Requiere: el resultado no debe estar en el rango [primero, último).
2 Efectos: Copia los elementos en el rango [primero, último) en el rango [resultado, resultado + (último - primero)) desde el primero hasta el último.
y:
template<class BidirectionalIterator1, class BidirectionalIterator2> BidirectionalIterator2 copy_backward( BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result);
17 Requiere: el resultado no debe estar en el rango (primero, último).
18 Efectos: Copia los elementos en el rango [primero, último) en el rango [resultado - (último-primero), resultado) desde el último - 1 y continúa hasta el primero. (263) Para cada entero positivo n <= (último - primero), realiza * (resultado - n) = * (último - n).
La nota luego explica cuándo usar copy_backward
:
263) copy_backward se debe usar en lugar de copiar cuando el último está en el rango [resultado - (último - primero), resultado)
Por lo tanto, no hay ningún requisito de superposición para esas funciones y, a diferencia de memcpy
, el comportamiento de las superposiciones se define claramente en las secciones de Effects
.
Simplemente elija entre ellos porque normalmente desea que std::copy
copie a la izquierda y std::copy_backward
para que se copie a la derecha.
C ++ también tiene una versión a distancia de std::move
en <algorithm>
que se mueve en lugar de copiar.