重载operator = break std :: sort

时间:2018-01-06 03:22:00

标签: c++ c++11 assignment-operator

可能是一个骗局,但我无法找到它。

在敲击键盘两天之后,我发现重载equals运算符(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进行编译,但没有警告。

2 个答案:

答案 0 :(得分:5)

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

将其更改为

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

  return *this;
}

std::sort通过移动元素对元素进行排序,使用operator=重载Person。这就是错误的实现在这里打破std::sort的原因。

BTW:当您删除实现时,自动生成的赋值运算符会为您做正确的事。

答案 1 :(得分:3)

您的operator=重载从根本上被打破:它会返回对象(而不是对*this的引用,这是强约定),而不会影响{{1}毕竟。