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

17

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

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 * & amp;)'

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

    
задан Maurice Rodriguez 09.04.2013 в 16:37
источник

4 ответа

19

Чтобы использовать диапазон-for-loop , вам необходимо предоставить функции begin() и end() или перегрузить функции non-member 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;

Обратите внимание, что функции 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;

Пример

    
ответ дан user2218982 10.04.2013 в 09:42
источник
16

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

std::vector<int> v(size);
for(const auto& elem: v)
    // do something
    
ответ дан soon 09.04.2013 в 16:40
источник
8

Вы не можете выполнять цикл, основанный на диапазоне, на динамически распределяемом массиве, потому что все, что у вас есть, является указателем на первый элемент. Нет информации о его размере, который компилятор может использовать для выполнения цикла. Идиоматическим решением на C ++ было бы заменить динамически выделенный массив на 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;
    
ответ дан juanchopanza 09.04.2013 в 16:48
источник
-1

Смотрите эту страницу Ссылка и найдите главу " member begin () и end () ". Это может быть то, чего вы хотите достичь.

    
ответ дан Zoka 09.04.2013 в 16:49
источник