Reputation: 189
I have
std::vector<MyObject> obs;
//fill obs...
std::vector<MyObject*> obsA;
std::vector<MyObject*> obsB;
for (MyObject &p: obs){
if (p.type == "A"){
obsA.push_back(p);
}else{
obsB.push_back(p);
}
}
where I am trying to create a 2 subsets of some vector of objects. I want the subsets to be pointers, so that any changes made to the object in the obsA or obsB is reflected in the main obs vector. However when I try to run the code I get the following error:
src/main.cpp:55:26: error: no matching function for call to ‘std::vector<MyObject*>::push_back(MyObject&)’
I thought that having & after a variable should give the address to that variable, and since obsA and obsB and vector of pointers, that it should be valid to insert an address of a MyObject into there. What am I doing wrong here?
Upvotes: 0
Views: 88
Reputation: 1287
I thought that having & after a variable should give the address to that variable, and since obsA and obsB and vector of pointers, that it should be valid to insert an address of a MyObject into there. What am I doing wrong here?
The most direct answer to your question would be to modify it in the following way. The p
is just a reference to some element in obs
. &p
gives you the address in memory to where p
is referencing, which is what the pointer needs.
for (MyObject &p: obs){
if (p.type == "A"){
obsA.push_back(&p);
}else{
obsB.push_back(&p);
}
}
The bigger question is why you are doing it this way. This seems very likely to break and do something bad. Anytime you modify the original vector obs
(by adding or removing elements), all the pointers in obsA
and obsB
can be invalidated (i.e., they no longer point to the right place in obs
). Changing the size of vector obs
can cause a memory reallocation and moving the contents of obs
to a new place in memory, which would be a different location from where the elements of obsA
and obsB
are pointing to. Then any further usage of obsA
or obsB
would cause undefined behavior, which would lead to abnormal behavior and a likely crash.
There are potential alternatives. For example, replacing the contents of obs
with std::shared_ptr<>
s can help, but if you remove one element from obs
this won't clean it up that element correctly in either obsA
or obsB
(i.e., either obsA
or obsB
will still hold that object in memory and it won't be deleted correctly). A combination of std::shared_ptr
and std::weak_ptr
could work:
std::vector<std::shared_ptr<Obj>> obs;
std::vector<std::weak_ptr<Obj>> obsA, obsB;
for (auto p: obs){
if (p->type == "A"){
obsA.push_back(p);
}else{
obsB.push_back(p);
}
}
//... later
for( auto it = obsA.begin(); it != obsA.end(); it++ ) {
if(auto p = (*it).lock()) { // lock tests if the shared_ptr is still valid
p->otherMemberVariable = "edit"; //This will also edit the same element in the vector obs
else {
//the pointer was removed from obs, remove it here too
it = obsA.erase(it);
}
}
But this is getting very complicated, so you may want to rethink your design a bit.
Upvotes: 1
Reputation: 50110
You need
obsA.push_back(&p);
Strongly recommend using shared_ptr rather than raw pointers tho
Upvotes: 0