вопрос новичка об указателе на STL - PullRequest
1 голос
/ 12 января 2011

Я написал эту функцию

vector<long int>* randIntSequence(long int n) {
    vector<long int> *buffer = new vector<long int>(n, 0);
    for(long int i = 0; i < n; i++)
        buffer->at(i);

    long int j; MTRand myrand;
    for(long int i = buffer->size() - 1; i >= 1; i--) {
        j = myrand.randInt(i);
        swap(buffer[i], buffer[j]);
    }
    return buffer;
}

, но когда я вызываю ее из main, myvec = randIntSequence (10), я вижу myvector всегда пустым.Должен ли я изменить возвращаемое значение?

Ответы [ 4 ]

5 голосов
/ 12 января 2011

Вызов swap индексирует указатель *buffer, как если бы он был массивом, и обменивается указателями. Вы хотите поменять местами элементы вектора. Попробуйте эту модификацию:

swap((*buffer)[i], (*buffer)[j]);

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

buffer->at(i) = i;
(*buffer)[i] = i;
4 голосов
/ 12 января 2011

Вы никогда не назначаете ни одному из элементов в vector, на который указывает buffer:

for (long int i = 0; i < n; i++)
    buffer->at(i); // do you mean to assign something here?

В результате вы получите vector, содержащее n нулей.

3 голосов
/ 12 января 2011

На ваш вопрос уже дан ответ, поэтому я сделаю это CW, но так должен выглядеть ваш код.

std::vector<long int> randIntSequence(long int n)
{
    std::vector<long int> buffer(n);
    for(int i=0; i<n; ++i)
        buffer[i] = i;
    std::random_shuffle(buffer.begin(), buffer.end());
    return buffer;
}

Нет абсолютно никаких причин, по которым вам следует использовать указатель здесь.И если у вас нет более продвинутого метода случайного тасования, вы должны использовать std::random_shuffle.Вы также можете использовать boost::counting_iterator для инициализации вектора:

std::vector<long int> buffer(
    boost::counting_iterator<long int>(0),
    boost::counting_iterator<long int>(n));

Хотя это может быть излишним.

1 голос
/ 12 января 2011

Поскольку вопрос касается STL, и все, что вам нужно, это вектор со случайными записями, то:

std::vector<long int> v(10);
generate( v.begin(), v.end(), std::rand ); // range is [0,RAND_MAX]

// or if you provide long int MTRand::operator()()  
generate( v.begin(), v.end(), MTRand() );

Но если вы хотите исправить свою функцию, тогда

  • n должно быть size_t не long int
  • Первый цикл не работает
  • Как говорит Джон, buffer - это указатель, поэтому buffer[0] - это ваш вектор, а buffer[i] для i!=0 - это мусор. Кажется, вам очень повезло получить вектор нулевого размера вместо поврежденного!
  • Вы намерены сделать случайное перемешивание? Если да, то вы тасуете нули. Если вы просто хотите сгенерировать случайные записи, то почему бы вам просто не зациклить вектор (от 0 до buffer-> size (), а не наоборот !!) и назначить ваше случайное число?

C ++ не является сборщиком мусора, и вам, вероятно, не нужны умные указатели для таких простых вещей, поэтому вы обязательно получите утечки. Если причина заключается в генерации вектора кучи и возврате по указателю, что позволяет избежать копирования из-за производительности, то я советую не делать этого! Ниже приведена (почти) идеальная альтернатива, как для ясности, так и для производительности:

vector<T> randIntSequence( size_t n ) { 
   vector<T> buffer(n);
   // bla-bla
   return buffer; 
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...