C++需要澄清代码

发布于 2024-08-31 04:28:35 字数 474 浏览 4 评论 0 原文

我试图理解下面的代码所说的内容:

structcompare_pq;

struct compare_pq {
    bool operator() (Events *& a, Events *& b);
};

std::priority_queue<Events *, std::vector<Events *>, compare_pq> eventList;

我查看了priority_queue是什么以及它是如何声明的,但无法停止理解compare_pq在priority_queue eventList中做什么。另外,operator() 是做什么的,因为我之前从未见过 *& 和空运算符重载 operator()

任何帮助将不胜感激。谢谢

I'm trying to understand what the code below says:

struct compare_pq;

struct compare_pq {
    bool operator() (Events *& a, Events *& b);
};

std::priority_queue<Events *, std::vector<Events *>, compare_pq> eventList;

i looked at what priority_queue is and how its declared but can't quit understand what compare_pq is doing in the priority_queue eventList. Also what does operator() do since i've never seen *& before and empty operator overloading operator()!

any help would be appreciated. Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风铃鹿 2024-09-07 04:28:35

operator() 是函数调用运算符。它允许您像使用函数一样使用类类型的对象,例如,

compare_pq my_comparator;
bool result = my_comparator(a, b);

重载operator() 的类类型的对象通常称为函数对象或函子。

std::priority_queue 的第三个模板参数用于比较函数。默认情况下,优先级队列使用 std::less 对其元素进行排序,这会将 operator< 应用于两个元素。您可以使用任何接受两个元素并返回一个布尔值的函数(或函数对象),指示第一个元素是否小于第二个元素。在这种情况下,“较小”是一个相对术语:优先级队列的 top() 是队列中当前“最大”的元素。

在这种情况下,您需要使用自定义比较函数,因为优先级队列存储指针,因此默认情况下它会按指针值对元素进行排序。自定义比较器(可能)取消引用指针并对指向的对象执行一些比较。

Events*& 只是对 Events 对象的指针的引用。它确实不需要通过引用传递。由于它只是一个指针,因此可以按值传递(例如,Events*)。如果您出于某种原因选择使用引用,那么它应该是 const 引用。

operator() is the function-call operator. It allows you to use an object of the class type as if it were a function, e.g.,

compare_pq my_comparator;
bool result = my_comparator(a, b);

Objects of class types that overload operator() are frequently called function objects or functors.

The third template parameter of std::priority_queue is for the comparison function. By default, the priority queue sorts its elements using std::less, which applies operator< to two elements. You can use any function (or function object) that takes two elements and returns a boolean indicating whether the first is smaller than the second. "Smaller" in this case is a relative term: the top() of the priority queue is the "largest" element currently in the queue.

In this case, you need to use a custom comparison function because the priority queue is storing pointers, so by default it would sort the elements by pointer value. The custom comparator (probably) dereferences the pointers and performs some comparison on the pointed-to objects.

Events*& is just a reference to a pointer to an Events object. It really doesn't need to be passed by reference. Since it's just a pointer, it can be passed by value (e.g., Events*). If you do choose for some reason to use a reference it should be a const reference.

Bonjour°[大白 2024-09-07 04:28:35

*&是对指针的引用。它的工作原理与任何其他类型的参考一样。在不太复杂的 C++ 代码中,您可能会看到使用双指针 (**)。

Compare_pq 是一个用于比较事件指针的函子。在这种情况下,每当需要比较时,priority_queue 可能会实例化一个compare_pq。

Event * a = new Event();
Event * b = a;
compare_pq foo;
bool result = foo(a, b);

运算符()不为空。您正在查看一份声明。如果要实例化它,则必须在其他地方定义它。

*& is a reference to a pointer. It works like any other kind of reference. In less sophisticated C++ code you might see a double pointer (**) used.

compare_pq is a functor used to compare Event pointers. In this case, priority_queue would likely be instantiating a compare_pq whenever a comparison is needed.

Event * a = new Event();
Event * b = a;
compare_pq foo;
bool result = foo(a, b);

operator() is not empty. You're looking at a declaration. It must be defined somewhere else if it is to be instantiated.

梦里寻她 2024-09-07 04:28:35

我将尝试回答为什么使用函子的问题。当然,这只是一个猜测,因为我不是代码的作者,但我至少看到过几次关于它的讨论,而且共识似乎是,函子启用或至少使内联比较代码变得更容易。

函子是结构(或类),通常比常规函数更灵活,因为它们可以有一些成员,存储一些状态,可供operator()使用。在这种情况下,没有使用此优势,因此仿函数最有可能用于启用(或帮助)内联,或者只是因为作者习惯了这种常见模式。

为什么它有助于内联?让我们看一个简单的例子。让我们以 std::sort 为例,

template <class RandomAccessIterator, class Compare>
  void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

假设您想要对 std::vector 进行排序,并且想要提供自定义比较器。

struct MyStructComp1
{
    bool operator()(int lhs, int rhs) const { /*...*/}
};

struct MyStructComp2
{
    bool operator()(int lhs, int rhs) const { /*...*/}
};

bool myFunctComp1 (int lhs, int rhs) const { /*...*/}
bool myFunctComp2 (int lhs, int rhs) const { /*...*/}

现在您可以通过以下方式使用 sort 模板

sort(myvector.begin(), myvector.end(), MyStructComp1()); // 1
sort(myvector.begin(), myvector.end(), MyStructComp2()); // 2
sort(myvector.begin(), myvector.end(), myFunctComp1);  // 3
sort(myvector.begin(), myvector.end(), myFunctComp2);  // 4

以下是编译器从模板创建的函数

sort<vector<int>::iterator, MyStrucComp1> // 1
sort<vector<int>::iterator, MyStrucComp2> // 2
sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> // 3, // 4

由于排序模板中的 Compare 参数是类型,而函子是类型,因此编译器会创建不同的函数作为模板参数提供的每个函子的函数。 sort::iterator, MyStrucComp1>
sort::iterator, MyStrucComp2> 是两个不同的函数。因此,当创建 sort::iterator, MyStrucComp1> 时,就可以准确地知道比较代码是什么,并且可以简单地内联比较器。

然而,函数 myFunctComp1 和 myFunctComp2 的类型完全相同:
bool (*) (int lhs, int rhs) 并且编译器创建一个函数 sort::iterator, bool (*) (int lhs, int rhs)> 适用于 bool (*) (int lhs, int rhs) 类型的所有比较函数。我看到了意见,在这种情况下无论如何内联都是可能的,但我不知道如何做。

可以使用指向函数的指针作为模板参数创建模板,因为它是编译时常量,但它很丑陋,并且无法从函数参数中推导出常量。例如,如果 sort 定义为:

template <class RandomAccessIterator,
bool (*comparer) (typename RandomAccessIterator::value_type, typename RandomAccessIterator::value_type)>
    void sort ( RandomAccessIterator first, RandomAccessIterator last) {/*   */}

您必须像这样调用它

sort<std::vector<int>::iterator, myFunctComp1>(myvector.begin(), myvector.end());

您将为每个比较函数获得不同的排序,但函子要方便得多。

I'll try to answer the question why a functor is used. It's just a guess of course, as I'm not the author of the code, but I saw discussions about it at least a few times and the consensus seems to be, that functors enable or at least make it easier to inline the comparison code.

Functors are structs (or classes) and in general are more flexible than regular functions because they can have some members, that store some state, which can be used by operator(). In this case this advantage isn't used, so the functor was most probably used to enable (or help) in inlining or just because the author was used to this common pattern.

Why would it help in inlining? Let's look at a simple example. Lets take std::sort

template <class RandomAccessIterator, class Compare>
  void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

Imagine You want to sort std::vector<int> and You want to provide Your custom comparators.

struct MyStructComp1
{
    bool operator()(int lhs, int rhs) const { /*...*/}
};

struct MyStructComp2
{
    bool operator()(int lhs, int rhs) const { /*...*/}
};

bool myFunctComp1 (int lhs, int rhs) const { /*...*/}
bool myFunctComp2 (int lhs, int rhs) const { /*...*/}

Now You can use the sort temeplate in the following ways

sort(myvector.begin(), myvector.end(), MyStructComp1()); // 1
sort(myvector.begin(), myvector.end(), MyStructComp2()); // 2
sort(myvector.begin(), myvector.end(), myFunctComp1);  // 3
sort(myvector.begin(), myvector.end(), myFunctComp2);  // 4

Here are the function the compiler creates form the template

sort<vector<int>::iterator, MyStrucComp1> // 1
sort<vector<int>::iterator, MyStrucComp2> // 2
sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> // 3, // 4

Since the Compare parameter in the sort template is a type, and functors are types, the compiler creates a different function for every functor supplied as a template argument. sort<vector<int>::iterator, MyStrucComp1> and
sort<vector<int>::iterator, MyStrucComp2> are two different functions. So when sort<vector<int>::iterator, MyStrucComp1> is created, it is known exactly what the comparing code is and the comparator can be simply inlined.

Functions myFunctComp1 and myFunctComp2 however are of exactly the same type:
bool (*) (int lhs, int rhs) and the compiler creates one function sort<vector<int>::iterator, bool (*) (int lhs, int rhs)> for all comparing functions of type bool (*) (int lhs, int rhs). I saw opinions, that inlining is possible anyway in this situation, but I have no idea how.

It is possible to create templates with a pointer to function as a template parameter as it's a compile time constant, but it's ugly and constants can't be deduced from the function arguments. For example if sort was defined as:

template <class RandomAccessIterator,
bool (*comparer) (typename RandomAccessIterator::value_type, typename RandomAccessIterator::value_type)>
    void sort ( RandomAccessIterator first, RandomAccessIterator last) {/*   */}

You would have to call it like this

sort<std::vector<int>::iterator, myFunctComp1>(myvector.begin(), myvector.end());

You would get a different sort for every comparing function, but functors are much more convenient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文