cccnrc
cccnrc

Reputation: 1249

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, e.g.

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!

Upvotes: 2

Views: 1285

Answers (3)

Jesper Juhl
Jesper Juhl

Reputation: 31459

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.

Upvotes: 1

Fureeish
Fureeish

Reputation: 13434

Short answer:

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

Yes.

You can instead use auto& to avoid copies.

Upvotes: 1

Radosław Cybulski
Radosław Cybulski

Reputation: 2992

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.

Upvotes: 3

Related Questions