C ++ автоматический итератор вектор присоединения элементов класса - PullRequest
2 голосов
/ 09 июня 2019

Извините, если это звучит глупо, я изо всех сил пытался избежать глупых вопросов в течение 3 часов и выяснил проблему, но, пытаясь понять ее глубже, я не нашел четкого ответа, поэтому я хотел бы, чтобы вы, ребята-эксперты, дали мне краткое «теоретическое» объяснение вектора поведения классов и его объекта присоединения.

Я заметил, что если я определю класс, например,

class Variant {
  std::map<std::string, std::string> attributes;
  public:
    void addAttr(std::string attr, std::string value){
      if ( !attributes.insert( std::make_pair( attr, value ) ).second ) std::cout << "inserted fail for: " << attr << " (attribute already present)" << '\n';
      attributes.insert( std::make_pair( attr, value ) );
    }
    std::string getValue(std::string attr){ return attributes.at(attr); }
};

и я помещаю его объекты в вектор:

std::vector<Variant> vVarClass;

for (int i = 0; i < 10; i++ ) {

    Vector tmp;

    tmp.addAttr("one", "first");
    tmp.addAttr("two", "second");
    tmp.addAttr("three", "third");

    vVarClass.push_back(tmp);

}

Затем я могу легко получить доступ к атрибутам объектов класса с помощью:

for ( auto var : vVarClass ) {
   std::cout << var.getValue("one") << '\n';
}

first
first
...

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

for ( auto var : vVarClass ) {
    var.addAttr("four", "fourth");
}

без ошибок, но:

for ( auto var : vVarClass ) {
    var.getValue("four");
}

terminate called after throwing an instance of 'std::out_of_range'
  what():  map::at
Aborted

потому что он не находит этот атрибут на карте. Но если доступ к каждому члену по его определенной позиции, это работает:

for ( int i = 0; i < vVarClass.size(); i++ ) {
    vVarClass[i].addAttr("four", "fourth");
}

for ( auto var : vVarClass ) {
    var.getValue("four");
}

fourth
fourth
...

Делает ли авто итератор «копию» объекта, вставляет ли атрибут в этот объект, но не в исходный?

Заранее большое спасибо за любую помощь!

Ответы [ 3 ]

3 голосов
/ 09 июня 2019

Вам нужна ссылка в вашем цикле.В противном случае вы работаете с копией, которая уничтожается.

for ( auto &var : vVarClass )

Также второй вызов .insert является избыточным - вставка будет вставлять или не вставлять (только если ключ уже существует), в обоих случаях она вернет итератор к существующемуключ-значение.

1 голос
/ 09 июня 2019

auto var сделает копию.const auto& var даст вам ссылку только для чтения (без копии).auto& var даст вам изменяемую ссылку (без копии, позволит вам изменить объект на месте).

Также помните, что auto не является особенным.Это просто означает «компилятор, пожалуйста, определите правильный тип для меня, поэтому мне не нужно его печатать».Конечный результат точно такой же , как если бы вы вводили вручную имя типа.

1 голос
/ 09 июня 2019

Краткий ответ:

Является ли автоматический итератор копированием объекта [...]

Да.

Вывместо этого можно использовать auto&, чтобы избежать копирования.

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