首页 > 解决方案 > 将 std::sort 与自定义类一起使用

问题描述

我在下面创建了一个最小的可重现示例:

多边形3D.h:

#pragma once
class Polygon3D
{
public:
    // Constructors
    Polygon3D();
    Polygon3D(const Polygon3D& p);
    // Accessors
    void SetAverageZ(float average);
    float GetAverageZ() const;
    // Operators
    Polygon3D& operator= (const Polygon3D& rhs);
    const bool operator< (const Polygon3D& rhs) const;
private:
    float _averageZ;
};

Polygon3D.cpp 文件:

#include "Polygon3D.h"
// Default constructor
Polygon3D::Polygon3D()
{
    _averageZ = 0;
}
// Copy constructor
Polygon3D::Polygon3D(const Polygon3D& p)
{
    _averageZ = p.GetAverageZ();
}
// Accessors
void Polygon3D::SetAverageZ(float average)
{
    _averageZ = average;
}
float Polygon3D::GetAverageZ() const
{
    return _averageZ;
}
// Operators
Polygon3D& Polygon3D::operator=(const Polygon3D& rhs)
{
    return *this;
}
// Used by std::sort to order lists of this class
const bool Polygon3D::operator<(const Polygon3D& rhs) const
{
    return _averageZ < rhs.GetAverageZ();
}

排序.cpp 文件:

#include <iostream>
#include <vector>
#include <algorithm>
#include "Polygon3D.h"

int main()
{
    std::vector<Polygon3D> list;

    Polygon3D temp1 = Polygon3D();
    temp1.SetAverageZ(2);
    list.push_back(temp1);

    Polygon3D temp2 = Polygon3D();
    temp2.SetAverageZ(0);
    list.push_back(temp2);

    Polygon3D temp3 = Polygon3D();
    temp3.SetAverageZ(6);
    list.push_back(temp3);

    Polygon3D temp4 = Polygon3D();
    temp4.SetAverageZ(5);
    list.push_back(temp4);

    std::sort(list.begin(), list.end(), std::less<Polygon3D>());

    std::cout << "Sorted vector: ";

    for (Polygon3D poly : list) 
    {
        std::cout << poly.GetAverageZ();
    }
}

这是我收到的输出:

Sorted vector: 2065

如您所见,向量没有被排序,而是按照添加项目的顺序输出。是否有原因导致未正确排序?任何帮助是极大的赞赏。

标签: c++sortingstdvector

解决方案


您已经定义了一个复制分配运算符,它实际上并不复制分配_averageZ成员。std::sort将使用它来交换向量的元素,但因为它实际上并没有改变任何成员,所以_averageZ向量中成员的排序将保持不变。

声明特殊成员函数时,您需要始终正确地实现它们。

但是,编译器确实定义了一个复制赋值运算符,只要满足某些条件,它就会隐式地为您做正确的事情。

只需从类中删除用户提供的复制赋值重载和复制构造函数定义和声明,它就会按预期工作,即删除Polygon3D(const Polygon3D& p);Polygon3D& operator= (const Polygon3D& rhs);及其实现。然后编译器将为您隐式定义一个正确工作的复制构造函数和复制赋值构造函数。

但是如果你必须声明这些特殊的成员函数,那么你需要_averageZ在复制赋值重载中实际复制成员。


推荐阅读