Подтвердить что ты не робот

Диапазон для цикла для динамического массива?

Существует цикл, основанный на диапазоне, с синтаксисом:

for(auto& i : array)

Он работает с постоянными массивами, но не с динамическими, основанными на указателях, например

int *array = new int[size];
for(auto& i : array)
   cout<< i << endl;

Он дает ошибки и предупреждения о сбое подстановки, например:

Ошибка] C:\Users\Siegfred\Documents\C-Free\Temp\Untitled2.cpp: 16: 16: ошибка: нет соответствующей функции для вызова 'begin (int * &)'

Как использовать этот новый синтаксис с динамическими массивами?

4b9b3361

Ответ 1

Чтобы использовать цикл for-loop для диапазона, вам необходимо предоставить функции-члены begin() и end() или перегрузить функции, не являющиеся членами begin() и end(). В последнем случае вы можете обернуть свой диапазон в std::pair и перегрузить begin() и end() для следующих:

    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; }
    }

Теперь вы можете использовать for-loop следующим образом:

    for (auto&& i : std::make_pair(array, array + size))
        cout << i << endl;

Обратите внимание, что функции non-member begin() и end() должны быть перегружены в пространстве имен std здесь, потому что pair также находится в пространстве имен std. Если вы не хотите вмешиваться в стандартное пространство имен, вы можете просто создать свой собственный крошечный класс пар и перегрузить begin() и end() в своем пространстве имен.

Или создайте тонкую оболочку вокруг вашего динамически выделенного массива и предоставите функции-члены begin() и 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}; }

И ваш сайт вызова выглядит следующим образом:

    for (auto&& i : wrap_array(array, size))
         std::cout << i << std::endl;

Пример

Ответ 2

Вы не можете использовать range-for-loop с динамически распределенными массивами, поскольку компилятор не может вывести начало и конец этого массива. Вы должны всегда использовать вместо него контейнеры, например std::vector.

std::vector<int> v(size);
for(const auto& elem: v)
    // do something

Ответ 3

Вы не можете выполнять цикл, основанный на диапазоне, на динамически распределяемом массиве, потому что все, что у вас есть, является указателем на первый элемент. Нет информации о его размере, который компилятор может использовать для выполнения цикла. Идиоматическим решением С++ было бы заменить динамически выделенный массив на std::vector:

std::vector<int> arr(size);
for(const auto& i : arr)
  std::cout<< i << std::endl;

Диапазон, основанный на цикле, работает для объектов std::array. Вы должны просмотреть экземпляр массива (arr), а не тип (array):

std::array<int,10> arr;
for(const auto& i : arr)
  std::cout<< i << std::endl;