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

Overloading operator= breaks std::sort

本文关键字:sort std 中断 运算符 重载      更新时间:2023-10-16

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

在双节棍两天后,我发现重载等于运算符(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);,我都会看到相同的行为,无论我使用 7.2.1 版还是 4.0.1 版g++ clang++我都会看到相同的行为。 我正在运行 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通过移动元素对元素进行排序,这使用重载的operator=进行Person。这就是为什么错误的实现在这里中断std::sort的原因。

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

>你的operator=重载从根本上被破坏了:它返回一个新对象(而不是像强约定那样对*this的引用(,而完全不影响*this