简体   繁体   中英

Why does std::sort() change the sorted vector?

here is the problem:

In my first class i have a vector, a double variable and I overload the comparison operators. Here is the relevant code:

class City
{
    double distance;
    std::vector<int> coordinates;

    bool operator<(const City& city) const
    {   
        return this->distance < city.distance;
    } 

    // same for the greater-than operator but changing "<" to ">"
};

In another class I have a vector of cities, which I have to sort every time a condition is met. For that I have a struct defined as follows:

EDIT: (reference instead of value)

struct CitySortHelper {
    bool operator() (const City &x, const City &y) const { return x < y; } 
} city_sort;

Now the problem part, when I sort the vector new City objects appear, and I can't explain why:

EDIT:

// this prints all current objects in the vector
for (int i = 0; i < totalCities; i++) {
    std::cout << cities->at(i) << std::endl;
}

// after the following line I get new City objects in the 
// vector, that weren't there before the sort. The new objects
// always have distance = 0 and random values in the coordinates
std::sort(cities->begin(), cities->end(), city_sort);

// using the sort with no predicate also gives the same faulty results
std::sort(cities->begin(), cities->end());

EDIT: (the copy constructor and assignment operator)

City(const City &city)
{
    this->distance = city.distance;
    this->coordinates = city.coordinates;
}

City& operator= (const City &city)
{
    this->distance = city.distance;
    this->coordinates = city.coordinates;

    return *this;
}

The weird part is that this only happens if I sort the City objects in ascending order, ie if I change the comparator operator in the CitySortHelper from "<" to ">" everything works fine.

Any ideas why this happens ?? Any help is appreciated.

CitySortHelper needs to take parameters by const reference, not by value. Another thing to keep in mind is that sort uses assignment operator for the City ; check that your assignment operator is working correctly. Taking care of these two issues should fix the problem.

You shouldn't use std::sort() if you want to preserve order, you should use std::stable_sort() . stable_sort guarantees elements maintain their relative order, sort doesn't.

Also, it doesn't seem like sort is your problem here. It seems there are City objects getting pushed into the vector somewhere, and you aren't noticing them because you're checking on a variable for size instead of the vector's iterators. Try printing like this instead and tell us what comes out:

for (std::vector <City> ::iterator it = cities->begin(); it != cities->end(); ++it) {
    std::cout << *it << std::endl;
}

Change your sort helper to have

bool operator() ( const City& x , const City& y) const

And also check that City copy constructor and assignment operator do the proper thing

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