2012-05-03 1 views
-1

У меня есть код, например:Использование станда :: random_shuffle с станд :: массив

typedef intptr_t ptr_t; 

const int num_elements = 100; 
ptr_t *pstr = (ptr_t *)malloc(sizeof(ptr_t) * num_elements); 
std::array<ptr_t,num_elements> *parray = new (pstr) std::array<ptr_t,num_elements>; 

Я хотел бы иметь возможность перетасовать элементы 1 к num_elements-2, так что я думал использовать зЬй :: перетасовать.

auto s = parray->begin()++; 
auto e = parray->end()--; 
std::random_shuffle (s, e); 

У меня есть жалоба, что для этого нет перегруженной функции. Я чувствую себя глупо в своей неспособности увидеть, что я делаю неправильно. Как мне это сделать правильно?

EDIT: из-за ответы и обратной связи, она изменилась в

auto s = parray->begin(); 
s++; 
auto e = parray->end(); 
std::random_shuffle (s, e); 

Однако, на «Авто е» я получаю: «авто» отличается уровней косвенности от 'междунар *

+0

Я никогда не видел арифметику итератора, примененную к 'end()' before. Кроме того, вы хотите '' '' '' '', а не временный 'begin() '. – chrisaycock

+0

Быстрое примечание: '++' и '--' не влияют на значения' s' и 'e', поскольку это происходит после назначения. Более того, это делается на временном, который затем быстро отбрасывается. – dasblinkenlight

+0

Почему вы так усложняетесь? Просто используйте 'new []'. – zvrba

ответ

5

В ответ на ваш прямой вопрос: я считаю, что ваша ошибка использует операторы приращения post, которые возвращают свое первоначальное значение перед приращением. Поскольку std::array итераторы в основном указатели, попробуйте

auto s = parray->begin() + 1; 
auto e = parray->end() - 1; 

Edit: Теперь, как и для остальных. Почему ты так поступаешь? Вы считали std::vector<int> arr(100) для создания динамического массива из 100 элементов? Он имеет схожие возможности, без всякой прямой манипуляции указателями?

Редактировать 2: После прочтения ваших комментариев, я понимаю, что проблема заключается в том, что вы пытаетесь перетасовать массив, который вы указали как указатель. В этом случае я бы не стал размещать новое вообще. Предполагая, что у вас есть указатель в pstr, это должно сработать.

std::random_shuffle(pstr +1, pstr + num_elements - 1); 

Это работает, потому что простые указатели в массиве будут работать как итераторы произвольного доступа для целей библиотеки алгоритмов.

+0

отредактированный вопрос. и о том, почему я использую прямые указатели, это долгая история, но это имеет смысл для моего использования. –

+0

Ну, это работает. Благодаря! Все еще любопытно узнать, почему он не будет работать с итераторами массивов, но вы исправили мою проблему. –

+0

@ std''OrgnlDave: Итераторов массива нет: 'std :: array :: begin()' и 'std :: array :: end() 'both return' T * '. – ildjarn

2

Даже если бы компилятор допустил это, ваш код не будет делать то, что вы хотите. Вы пытаетесь использовать post increment/decment для возвращаемых значений от begin()/end(), поэтому вы все равно присваиваете исходные значения s и e, а затем (если возможно), увеличивая/уменьшая время, которое они возвращают. Вы, видимо, хотите изменить присваиваемые значения.

auto s= parray->begin(); 
auto e= parray->end(); 

++s; 
--e; 

std::random_shuffle(s, e); 

Или, так как вы, очевидно, имеют случайные итераторы доступа в любом случае:

std::random_shuffle(parray->begin()+1, parray->end()-1); 

Я не уверен, почему вы динамическое выделение std::array - это, кажется, в значительной степени поражения точку использования std::array для начала.

+0

отредактированный вопрос, как вы говорите, не работает. см. править. однако std :: array, являющийся местом размещения new'd поверх массива, является частью упрощения для этого вопроса, это не фактический порядок кода –

+0

@ std''OrgnlDave: проблема, которую вы цитируете в редактировании звучит очень похоже на проблему с компилятором - вся точка «auto» заключается в том, что она должна генерировать правильный тип для соответствия назначаемому значению. Если это так, то, вероятно, проще всего изменить его на 'int * s = ...; int * e = ...; ' –