重载运算符 = 中断 std::sort

Overloading operator= breaks std::sort

可能是个骗子,但我找不到。

在用双节棍敲打我的键盘两天后,我发现重载等号运算符 (operator=) 显然会破坏 std::sort。也许我错误地重载了 operator=?这是我的 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;
}

如果我按原样运行此代码,则每个人不会根据年龄排序。 PrintPeople 以我初始化 people 的相同顺序打印出来。但是,如果我注释掉整个 Person operator= 函数,那么 people 根据年龄升序打印出来。无论我调用 std::sort(people.begin(), people.end()); 还是 std::sort(people.begin(), people.end(), Person::SortPeople);,我都会看到同样的行为,无论我使用 g++ 版本 7.2.1 还是 clang++ 版本 4.0.1,我都会看到同样的行为。我正在 运行正在安装 Fedora 27。

任何人都知道 为什么 重载 operator= 会中断 std::sort

我正在使用标记 -Wall -Wextra -Wconversion -std=c++11 进行编译,没有警告。

是的,您 operator= 超载是错误的。它应该在 *this 上修改,但您正在修改本地对象 newP

改为

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

  return *this;
}

std::sort 通过移动元素对元素进行排序,它使用 Person 的重载 operator=。这就是为什么错误的实现会在此处中断 std::sort

顺便说一句:当您删除实现时,自动生成的赋值运算符会为您做正确的事情。

您的 operator= 重载从根本上被破坏了:它 returns 一个 new 对象(而不是对 *this 的引用,强约定)完全不影响 *this