tutorial smart remix español curso aprender c++ arrays c++11 foreach dynamic-arrays

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?



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;

Ejemplo vivo .


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;

Example