Как изменить векторный элемент в C ++? - PullRequest
4 голосов
/ 23 ноября 2011

У меня есть вектор структур в C ++, и я хотел бы изменить каждый элемент в отдельности.Я обнаружил, что выполнение SomeStruct info = myVector[i] дает мне копию предмета, поэтому, если я изменю его, ничего не изменится.Итак, сейчас я перезагружаю элемент так: myVector[i] = info.Есть ли более эффективный способ сделать это?Тот, который не будет включать операцию копирования?

Это мой текущий код:

struct CharacterInfo {
    QChar character;
    int occurrences;
    double frequency;
};

std::vector<CharacterInfo> characterInfos;

// Some code to populate the vector

for (unsigned i = 0; i < characterInfos.size(); i++) {
    CharacterInfo info = characterInfos[i];
    info.frequency = (double)info.occurrences / (double)totalOccurrences;
    characterInfos[i] = info; // how to avoid this?
}

Ответы [ 4 ]

12 голосов
/ 23 ноября 2011

Самый простой способ, который не сильно меняет ваш код, это просто использовать ссылку вместо экземпляра.Итак:

SomeStruct & info = myVector[i];

Следующий простой способ - это перейти от использования цикла с индексом, например:

for (std::vector<SomeStruct>::iterator it = myVector.begin(); it != myVector.end(); ++it)
{
    SomeStruct & info = *it;
    // do stuff here
}

С STL вы можете пойти еще дальше, особенно если выиметь компилятор с поддержкой C ++ 11, например:

std::for_each(std::begin(myVector), std::end(myVector), [](SomeStruct & info) { /* do stuff here */ });

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

std::for_each(std::begin(myVector), std::end(myVector), std::mem_fun(&SomeStruct::calculateFrequency));

Это также будет работать без компилятора C ++ 11, если вы измените вызовы на std::begin(myVector) с myVector.begin() и то же самое для end.

8 голосов
/ 23 ноября 2011

Вы можете использовать ссылку:

CharacterInfo& info = characterInfos[i];
info.frequency = (double)info.occurrences / (double)totalOccurrences;

Ссылка info связана с элементом вашего вектора. Если вы измените его, вы измените элемент вектора тоже.

3 голосов
/ 23 ноября 2011

Вы можете перебирать вектор с помощью итератора STL:

for (vector<CharacterInfo>::iterator it = characterInfos.begin();
        it != characterInfos.end(); ++it) {
    it->frequency = (double)it->occurrences / totalOccurrences;
}

В цикле it является итератором, который имеет в основном ту же функциональность и интерфейс, что и указатель на структуру CharacterInfo: http://cplusplus.com/reference/std/iterator/RandomAccessIterator/

Зацикливание с помощью итератора является более идиоматическим способом итерации по каждому элементу std::vector, если вам не нужно знать индекс каждого элемента.

1 голос
/ 23 ноября 2011

Я не уверен, что понимаю ваш вопрос, но думаю, вы пытаетесь это сделать?

for (unsigned i = 0; i < characterInfos.size(); i++) {
    characterInfos[i].frequency = (double)characterInfos[i].occurrences / (double)totalOccurrences;
}

Другой вариант - использовать итераторы:

for(std::vector<CharacterInfo>::iterator it = characterInfos.begin(); it != characterInfos.end(); ++it){
    it->frequency = (double)it->occurences / (double)totalOccurences;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...