简体   繁体   中英

Overloading operator= breaks std::sort

Probably a dupe, but I can't find it.

After two days of nunchucking my keyboard, I have discovered that overloading the equals operator ( operator= ) apparently breaks std::sort . Maybe I'm overloading operator= incorrectly? This is my MCVE:

#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
#include <cstdint>
#include <vector>

struct Person
{
  std::string name;
  uint32_t age;

  bool operator< (const Person& p)
  {
    return this->age < p.age;
  }

  Person operator= (const Person& p)
  {
    Person newP;
    newP.name = p.name;
    newP.age = p.age;

    return newP;
  }

  static bool SortPeople(const Person& p1, const Person& p2)
  {
    return p1.age < p2.age;
  }
};

void PrintPeople(const std::vector<Person>& people)
{
  std::cout << "============ people begin" << std::endl;
  for (const auto& pIt : people)
  {
    std::cout << "name: " << pIt.name << ", age: " << pIt.age << std::endl;
  }
  std::cout << "============ people end" << std::endl;
}

int main()
{
  std::vector<Person> people = { { "james", 12 },
                                 { "jada", 4   },
                                 { "max", 44   },
                                 { "bart", 7   }
                               };

  PrintPeople(people);


  std::sort(people.begin(), people.end());
  PrintPeople(people);  

  return 0;
}

If I run this code as is, each person is not sorted based on age. PrintPeople prints out in the same order that I initialized people in. However, if I comment out the entire Person operator= function, then people does get printed out in ascending order based on age. I see this same behavior whether I call std::sort(people.begin(), people.end()); or std::sort(people.begin(), people.end(), Person::SortPeople); , and I see this same behavior whether I use g++ version 7.2.1 or clang++ version 4.0.1. I'm running Fedora 27.

Anyone have any idea why overloading operator= breaks std::sort ?

I'm compiling with flags -Wall -Wextra -Wconversion -std=c++11 ,, there are no warnings.

Yes you're overloading operator= wrongly. It's supposed to modify on *this , but you're modifying on a local object newP .

Change it to

Person& operator= (const Person& p)
{
  name = p.name;
  age = p.age;

  return *this;
}

std::sort sorts elements by moving them, which uses the overloaded operator= for Person . That's why the wrong implementation breaks std::sort here.

BTW: When you remove the implementation, the auto-generated assignment operator does the right thing for you.

你的operator= overload从根本上被破坏了:它返回一个对象(而不是对*this的引用,就像强大的约定一样)而不会影响*this

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