简体   繁体   中英

C++ auto iterator vector of class elements accession

Sorry if it may sound silly, I struggled 3 hours to avoid making silly questions and I figured out the problem, but trying to understand it more deeply I found no clear answer, so I'd like you expert guys give me a brief "theoretical" explanation about vector of classes behavior and its object accession.

I've noticed that if I define a class, eg

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); }
};

and I put its objects in a vector:

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);

}

I can then easily access attributes of the class objects with:

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

first
first
...

but if I try to add attributes through the class vector loop it does not insert it to the map:

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

no error, but:

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

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

cause it does not find this attribute in the map. But if access each members by its specific position it works:

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

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

fourth
fourth
...

Is the auto iterator making a "copy" of the object, insert the attribute in this object but not in the original one?

Thanks a lot in advance for any help!

You need reference in your loop. Otherwise you operate on copy, which gets destroyed.

for ( auto &var : vVarClass )

Also second .insert call is redundant - insert will either insert or not (only if key already exists), in both cases it will return iterator to existing key-value.

Short answer:

Is the auto iterator making a "copy" of the object [...]

Yes.

You can instead use auto& to avoid copies.

auto var will make a copy. const auto& var will give you a read-only reference (no copy). auto& var will give you a modifiable reference (no copy, will let you modify the object in-place).

Also remember that auto is not special. It just means "compiler, please figure out the right type for me, so I don't have to type it". The end result is exactly the same as if you had manually typed in the type name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM