简体   繁体   中英

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

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.

std::sort只会在向量中移动对象,但指针本身仍将指向它们最初指向的相同内存位置。

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.

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.

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

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