LPmore
LPmore

Reputation: 45

std::sort on a vector of Objects containing Objects* pointers

Let's say I define the following struct:

struct dockPose {
    Complex* pose;
    int Cluster;
    struct dockPose* DP;
    float Distance;
    int Density;
};
typedef struct dockPose DockPose;

Then, I declare a vector which will be sorted by Density value using the std::sort() function. After the call to std::sort, will my DockPose* DP pointers still point to the same DockPose instance it was pointing before? If not, what can I do to be sure DP pointers points to the same DockPose it was pointing to before sorting (if there is anything I can do) ?

Upvotes: 1

Views: 974

Answers (5)

Benjamin Lindley
Benjamin Lindley

Reputation: 103733

Yes, the pointers will still point to the same instance. But that may not be what you actually want. When you call std::sort on a vector, it does not change the location of instances (that's not even a thing you can do in C++). It swaps their values with each other. This is probably better explained with a simplified example. Take this struct:

struct Foo
{
    int x;
    Foo* buddy;
};

bool operator<(Foo const& lhs, Foo const& rhs)
{
    return lhs.x < rhs.x;
}

Now, lets say I make a vector of these, with decreasing x values, and each one having a pointer to the one that comes after it (and the last having a pointer to the first):

std::vector<Foo> vec(5);
for (int i = 0; i < 5; ++i)
{
    vec[i].x = 4 - i;
    vec[i].buddy = &vec[(i + 1) % 5];
}

Now, if I sort this vector, it is essentially going to reverse. But the instances themselves don't change their location. Instead, their values change such that the first one has the lowest x value, and it increases from there. Now, the pointer member changes along with the x value.

So take, for example, vec[0], which had an x value of 4, and a pointer to vec[1] (which has an x value of 3). After the sort, those values will end up in the last element, vec[4]. So vec[4] will have an x value of 4, and a pointer to vec[1] (which, after the sort, has an x value of 1).

So, before the sort, the element with the x value 4, had a pointer to the element with an x value of 3. After the sort, the element with the x value of 4 has a pointer to the element with the x value of 1. I doubt this is what you wanted.

Since you are interested in the identity of the instances, not just their values, you should probably be using something like std::vector<std::unique_ptr<dockPose>>. For my Foo example, I could do something like this:

std::vector<std::unique_ptr<Foo>> vec;
for (int i = 0; i < 5; ++i)
    vec.emplace_back(new Foo);
for (int i = 0; i < 5; ++i)
{
    vec[i]->x = 4 - i;
    vec[i]->buddy = vec[(i + 1) % 5].get();
}

Note that when you do this, you need to use a different comparison function. One which compares the dereferenced pointers, rather than the pointers themselves.

Upvotes: 3

DaveB
DaveB

Reputation: 341

keeping pointers to objects in a vector is not a good idea. Even a simple push_back() could make all of your pointers invalid, if you happen to cause a resize. If you want to keep pointers to objects in a container you would be better to use a std::list

Upvotes: 0

Alan Stokes
Alan Stokes

Reputation: 18974

If you have a vector of DockPose objects you are treating them as values, in which case it's a bad idea to keep pointers to them. I suspect you actually want them to be entities (two entities are distinct even if they have identical values).

In which case you should instead have a vector of pointers to the entities; sorting the vector of pointers will then not invalidate your DP pointers.

Upvotes: 0

SCC
SCC

Reputation: 720

Sorting will not change the values of those pointers. Pointers are simply variables holding memory addresses, sorting a vector will not change any of the member variable data of the objects in the vector.

Upvotes: 0

vsoftco
vsoftco

Reputation: 56567

std::sort will just move the objects around in the vector, but the pointers themselves will still point to the same memory location they pointed initially.

Upvotes: 0

Related Questions