c++ - smart - solidity español
Rango basado en bucle en una matriz dinámica? (6)
C ++ 20 (probablemente) agregará std::span
, que permite bucles como estos:
#include <iostream>
#include <span>
int main () {
auto p = new int[5];
for (auto &v : std::span(p, 5)) {
v = 1;
}
for (auto v : std::span(p, 5)) {
std::cout << v << ''/n'';
}
delete[] p;
}
Desafortunadamente, esto no parece ser compatible con los compiladores actuales en el momento de la escritura.
Por supuesto, si tiene la opción, es preferible usar std::vector
sobre arreglos de estilo C desde el principio.
Hay un bucle for basado en rango con la sintaxis:
for(auto& i : array)
Funciona con matrices constantes pero no con dinámicas basadas en punteros, como
int *array = new int[size];
for(auto& i : array)
cout<< i << endl;
Da errores y advertencias sobre la falla de la sustitución, por ejemplo:
Error] C: / Users / Siegfred / Documents / C-Free / Temp / Untitled2.cpp: 16: 16: error: no hay una función coincidente para la llamada a ''begin (int * &)''
¿Cómo uso esta nueva sintaxis con matrices dinámicas?
Consulte esta página http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer y busque el capítulo "non-member begin () and end ()". Esto podría ser lo que quieres lograr.
En lugar de definir std::begin
y std::end
para std::pair
de punteros (definirlos en std::
, por cierto, es en.cppreference.com/w/cpp/language/extending_std ) y desplegar su propio envoltorio, como se sugirió antes , puede usar boost::make_iterator_range
:
size_t size = 16;
int *dynamic_array = new int[size];
for (const auto& i : boost::make_iterator_range(dynamic_array, dynamic_array + size))
std::cout << i << std::endl;
No puede realizar un bucle basado en rango directamente sobre una matriz asignada dinámicamente porque todo lo que tiene es un puntero al primer elemento. No hay información sobre su tamaño que el compilador pueda usar para realizar el bucle. La solución idiomática de C ++ sería reemplazar la matriz asignada dinámicamente por un std::vector
:
std::vector<int> arr(size);
for(const auto& i : arr)
std::cout<< i << std::endl;
Alternativamente, podría usar un tipo de rango que proporcione un iterador de inicio y finalización basado en un puntero y un desplazamiento. Eche un vistazo a algunos de los tipos en la biblioteca boost.range , o en la propuesta de boost.range GSL (ejemplo de implementación here , referencia para el tipo propuesto de C ++ 20 here ).
Tenga en cuenta que un rango basado en bucle funciona para los objetos std::array
de arreglos de tamaño de arreglos simples:
std::array<int,10> arr;
for(const auto& i : arr)
std::cout<< i << std::endl;
int arr[10] = .... ;
for(const auto& i : arr)
std::cout<< i << std::endl;
pero en ambos casos, el tamaño debe ser una constante de compilación.
No puede usar el rango por bucle con matrices asignadas dinámicamente, ya que el compilador no puede deducir el comienzo y el final de esta matriz. Siempre debe usar contenedores en lugar de él, por ejemplo, std::vector
.
std::vector<int> v(size);
for(const auto& elem: v)
// do something
Para utilizar el bucle for basado en rango, debe proporcionar las funciones miembro begin()
y end()
o sobrecargar las funciones begin()
y end()
no miembros. En este último caso, puede ajustar su rango en un std::pair
y overload begin()
y end()
para esos:
namespace std {
template <typename T> T* begin(std::pair<T*, T*> const& p)
{ return p.first; }
template <typename T> T* end(std::pair<T*, T*> const& p)
{ return p.second; }
}
Ahora puedes usar el for-loop así:
for (auto&& i : std::make_pair(array, array + size))
cout << i << endl;
Tenga en cuenta que las funciones begin()
y end()
que no son miembros deben estar sobrecargadas en el std
nombres std
aquí, porque el pair
también reside en el espacio std
nombres. Si no tiene ganas de manipular el espacio de nombres estándar, simplemente puede crear su propia clase de par diminuto y begin()
sobrecarga begin()
y end()
en su espacio de nombres.
O bien, cree una envoltura delgada alrededor de la matriz asignada dinámicamente y proporcione las funciones de miembros begin()
y end()
:
template <typename T>
struct wrapped_array {
wrapped_array(T* first, T* last) : begin_ {first}, end_ {last} {}
wrapped_array(T* first, std::ptrdiff_t size)
: wrapped_array {first, first + size} {}
T* begin() const noexcept { return begin_; }
T* end() const noexcept { return end_; }
T* begin_;
T* end_;
};
template <typename T>
wrapped_array<T> wrap_array(T* first, std::ptrdiff_t size) noexcept
{ return {first, size}; }
Y su sitio de llamadas se ve así:
for (auto&& i : wrap_array(array, size))
std::cout << i << std::endl;