用于对包含指向自定义类对象的指针的向量进行排序的比较器
Posted
技术标签:
【中文标题】用于对包含指向自定义类对象的指针的向量进行排序的比较器【英文标题】:comparator for sorting a vector contatining pointers to objects of custom class 【发布时间】:2016-10-16 00:26:49 【问题描述】:通过这个问题,我也试图了解 C++ 的基础知识,因为我对 C++ 非常陌生。对自定义类的向量/列表进行排序的问题有很多很好的答案,例如this。在所有示例中,传递给 sort 的比较器函数的签名都是这样的:
(const ClassType& obj1, const ClassType& obj2)
此签名对于比较器功能是强制性的吗?或者我们也可以给出这样的东西:
(ClassType obj1, ClassType obj2)
假设我会相应地修改比较器的主体。
如果第一个签名是强制性的,那为什么? 我想了解使用 const 和 reference'&' 背后的原因。 我能想到的是 const 是因为您不希望比较器函数能够修改元素。并且引用是为了不创建多个副本。
如果我想对包含指向自定义类对象的指针的向量进行排序,我的签名应该如何?像(1)或(2)(见下文)或两者都有效? 待排序的vertor是vector类型
(1)
(const ClassType*& ptr1, const ClassType*& ptr2)
(2)
(ClassType* ptr1, ClassType* ptr2)
【问题讨论】:
我认为您不想比较指针?你?即使数组包含指向对象的指针,我认为您可能想比较对象的实际实例对吗? “我也在尝试了解 C++ 的基础知识,因为我对 C++ 还很陌生。” 你在用哪本书? 【参考方案1】:我建议查看This Documentation。
说明比较函数的签名必须等价到:
bool cmp(const Type1& a, const Type2& b);
更准确地说,它接着解释每个参数都需要是一种类型,该类型可以从通过将 迭代器 解引用到排序函数。
因此,如果您的迭代器是std::vector<ClassType*>::iterator
,那么您的参数需要可隐式转换为ClassType*
。
如果您使用的是相对较小的东西,例如 int
或 pointer
,那么我会按价值接受它们:
bool cmp(ClassType* ptr1, ClassType* ptr2) // this is more efficient
【讨论】:
【参考方案2】:(ClassType obj1, ClassType obj2)
在大多数情况下,此签名也适用于比较器。不使用它的原因是因为您必须意识到这是按值传递对象,这需要复制对象。
这完全是浪费。比较器函数不需要有自己的参数副本。它所需要的只是对它需要比较的两个对象的引用,仅此而已。此外,比较器函数不需要修改它正在比较的对象。它不应该那样做。因此,显式使用 const 引用会强制编译器发出编译错误,如果比较器函数被错误编码以修改对象。
这绝对行不通的一种情况是删除了复制构造函数的类。这些类的实例根本无法复制。您仍然可以emplace
将它们放入容器中,但它们不能被复制。但它们仍然可以比较。
【讨论】:
谢谢!。但是指针向量的情况应该怎么做呢?不存在复制问题。 const 对指针的使用也有意义吗? “在大多数情况下,此签名也可以工作”,而不是当类型不可复制时。 在简单指针的情况下,差别很小。一个好的编译器最终可能会编译相同的内联代码。【参考方案3】:const 是为了让您知道在比较它们时不要更改值。引用是因为您不想在尝试比较它们时复制该值——它们甚至可能不可复制。
它应该看起来像您的第一个示例——它始终是对向量元素的 const 类型的引用。
如果你有向量,它总是:
T const & left, T const & right
因此,如果 T 是指针,则比较的签名包括比较。
【讨论】:
我猜你会使用像 std::sort en.cppreference.com/w/cpp/algorithm/sort 这样的东西你没有“传递”参考。如果您调用的对象有引用,则会自动进行引用。 那么签名应该是什么样的?类型 (1) 或类型 (2) 有问题。 “它应该看起来像你的第一个例子” 是的,所以我的问题是。如果是指针向量?不存在复制元素的问题。这里只有指针会被复制以防传值。 const 对指针的使用也有意义吗? 无论向量中的类型是什么,都是您放入比较器的类型。只是从字面上复制/粘贴出来。【参考方案4】:STL 并没有什么特别之处。我使用它有两个主要原因,作为一个稍微方便的数组(std::vector),以及因为平衡二叉搜索树实现起来很麻烦。 STL 具有比较器的标准签名,因此所有算法都被编写为对 '' 操作或 C qsort() 约定,如果需要,您可以编写自己的模板化排序例程来执行此操作。但是,如果一切都使用相同的约定,则使用 C++ 会更容易。
比较器采用 const 引用,因为比较器不应该修改它所比较的内容,而且对于对象而言,引用比按值传递更有效。如果您只想对整数进行排序(在实际程序中很少需要对原始整数进行排序,尽管这通常作为练习完成),您很可能编写自己的按值传递的排序,并且比 STL 快一点结果排序。
【讨论】:
以上是关于用于对包含指向自定义类对象的指针的向量进行排序的比较器的主要内容,如果未能解决你的问题,请参考以下文章