重载运算符 = 中断 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
。
可能是个骗子,但我找不到。
在用双节棍敲打我的键盘两天后,我发现重载等号运算符 (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
。