c ++ вектор строк - проблема с указателями - PullRequest
1 голос
/ 13 сентября 2010

Я пытаюсь написать метод, который получает вектор строк и возвращает указатель на случайный элемент.Подскажите, пожалуйста, в чем проблема со следующим кодом?

string* getRandomOption(vector<string> currOptions){
    vector<string>::iterator it;
    it=currOptions.begin(); 
    string* res;

    int nOptions = currOptions.size();

    if(nOptions != 1){
        int idx = rand() % (nOptions-1);

        while (idx!=0){
            it++;
            idx--;
        };

    };


    res = &(*it);
};

Спасибо, Ли

Ответы [ 6 ]

10 голосов
/ 13 сентября 2010

Зачем возвращать указатель? Сохраняйте это простым!

std::string random_option(const std::vector<std::string>& options)
{
    return options[rand() % options.size()];
}

И так как это работает для любого типа, не только для строк, я бы предпочел общее решение:

template <typename T>
T random_element(const std::vector<T>& options)
{
    return options[rand() % options.size()];
}
5 голосов
/ 13 сентября 2010

Если вы хотите «вернуть указатель на случайный элемент», вам нужно передать ссылку на ваш вектор. На данный момент скопировано !

Вы должны сделать:

string* getRandomOption(vector<string> & currOptions)

Кстати, в вашей функции на данный момент нет return, вам нужно добавить инструкцию return для отправки вашего указателя.

4 голосов
/ 13 сентября 2010

Лучшая версия того же , потому что она работает с любым контейнером, а не только с векторами.Вот версия C ++ 03:

template <typename ForwardIterator>
ForwardIterator random_element(ForwardIterator begin, ForwardIterator end)
{
    typename std::iterator_traits<ForwardIterator>::difference_type
        size = std::distance(begin, end);
    if (size) //divide by zero errors are bad
        std::advance(begin, std::rand() % size);
    return begin;
}

Если вы работаете на C ++ 11, вы можете заменить вышеприведенное на следующее:

template <typename ForwardIterator>
ForwardIterator random_element(ForwardIterator begin, ForwardIterator end)
{
    auto size = std::distance(begin, end);
    if (size) //divide by zero errors are bad
        std::advance(begin, std::rand() % size);
    return begin;
}

, что обходит std::iterator_traits<t>::difference_type клей.

3 голосов
/ 13 сентября 2010

Вы передаете вектор по значению, то есть функция имеет локальную копию исходного вектора.Затем вы [намереваетесь] вернуть указатель на элемент в этом векторе.Но когда вы возвращаетесь из функции, эта локальная копия уничтожается, а ваш указатель остается висящим.

1 голос
/ 13 сентября 2010

Помимо других проблем, упомянутых в других ответах, при изменении размера вектора любые указатели или итераторы (или ссылки любой природы) становятся недействительными. Не возвращайте указатель.

1 голос
/ 13 сентября 2010

возможно, вы захотите изменить прототип вашей функции на:

const string* getRandomOption(const vector<string>& currOptions)

или

string* getRandomOption(vector<string>& currOptions)

, иначе вы просто получите элемент из временной копии.

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