Reputation: 1249
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
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
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
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