有助于理解函数对象的工作原理吗?

发布于 2024-10-14 19:22:47 字数 859 浏览 8 评论 0原文

我在 Wikipedia 上找到了这段代码

class compare_class {
  public:
  bool operator()(int A, int B) const {
    return A < B;
  }
};
...
// Declaration of C++ sorting function.
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
...
int main() {
    int items[] = {4, 3, 1, 2};
    compare_class functor;
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
}

起初我想知道 A 和 B 参数是如何传递给运算符的( )(int A, int B),当在 sort_ints 中提到函子时,甚至没有任何括号。

然后我发现 A 和 B 被传递给 sort_ints 函数内的函数对象。但是,既然 sort_ints 接收的是函数的地址,那么它的声明不应该有 'ComparisonFunctor*** c' 而不是 'ComparisonFunctor c' 吗?

在 sort_ints 函数内部,对函子的函数调用会像这样完成吗?

functor(*begin_items, *(begin_items+1));

I found this code on Wikipedia

class compare_class {
  public:
  bool operator()(int A, int B) const {
    return A < B;
  }
};
...
// Declaration of C++ sorting function.
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
...
int main() {
    int items[] = {4, 3, 1, 2};
    compare_class functor;
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
}

At first I wondered how the A and B parameters got passed to operator()(int A, int B), when the functor was mentioned in sort_ints without even any parenthesis.

Then I figured that A and B are being passed to the function object inside the sort_ints function. But then, shouldn't the declaration of sort_ints have 'ComparisonFunctor*** c' instead of 'ComparisonFunctor c', since it's receiving the address of a function?

Inside the sort_ints function, would the function call to the functor be done something like this?

functor(*begin_items, *(begin_items+1));

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

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

发布评论

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

评论(4

无声无音无过去 2024-10-21 19:22:47

要理解为什么 sort_ints 按值获取其参数,您必须记住作为比较器传递给它的对象不一定是函数指针。例如,如果您使用 compare_class 函数对象进行比较,那么您传递给函数的就是 compare_class 类型的具体对象。您没有传入 compare_class::operator() 的地址,因为 operator() 是成员函数,而不是自由函数。也就是说,以下代码:

compare_class myComparator;
myComparator(a, b);

翻译为

compare_class myComparator;
myComparator.operator() (a, b);

因此,参数需要按值而不是指针接收比较器,因为它需要一个接收者对象,而不是指向成员函数的指针或指向接收者对象的指针。

To understand why sort_ints takes its parameter by value, you have to remember that the object being passed into it as the comparator is not necessarily a function pointer. If, for example, you're using the compare_class function object to do the comparison, then what you're passing into the function is a concrete object of type compare_class. You're not passing in the address of compare_class::operator(), since operator() is a member function, not a free function. That is, the following code:

compare_class myComparator;
myComparator(a, b);

translates into

compare_class myComparator;
myComparator.operator() (a, b);

Consequently, the parameter needs to take in the comparator by value rather than by pointer, since it needs a receiver object, rather than a pointer to a member function or a pointer to the receiver object.

始终不够爱げ你 2024-10-21 19:22:47

正如您所指出的, sort_ints 的使用中没有任何内容暗示其对比较函子的要求:

compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);

sort_ints 本身也没有任何内容:

template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);

在 class_compare 中,我们只能通过观察它不提供其他功能来推断将使用的功能功能:

class compare_class
{
  public:
     bool operator()(int A, int B) const { return A < B; }
};

编译器确实会保留它,直到它尝试使用实例化的类型来编译 sort_ints 的实现,然后才确定这一切是否挂在一起。 sort_ints 必须具有您提到的那种声明:

c(*begin_items, *(begin_items+1));    // note: functor argument is "c"

因此,您的理解在所有方面都是正确的。但是,值得注意的是,提议的名为 Concepts 的 C++0x 功能旨在使 sort_int 的要求更加明确,而无需查看其实现。不幸的是,C++0x 不得不放弃这个功能,因为没有足够的时间和经验来确保它是最佳的。希望 C++ 的未来版本能够包含这样的功能。您可以在网上找到很多有关概念的讨论,它们应该可以帮助您更好地理解整个问题。

这是一个重要的问题,因为当您只有拼图的一部分时 - 例如您想要使用 sort_ints 函数但没有示例 ComparisonFunctor,那么您必须研究 sort_ints 的实现以知道如何创建该 Functor(除非您是超级幸运,并且有很好的最新文档)。您可能会意外地使您的代码过于依赖于现有的实现,从而当 sort_int 的实现稍稍更改时,您的代码会中断或速度减慢,无法接受 - 即使它足够巧妙地不会破坏测试用例或其他用户的代码或期望。所提供的 ComparisonFunctor 中的一个小错误也可能会从 sort_int 内部的某个地方产生非常复杂和令人困惑的编译器错误消息 - 这不是为用户提供抽象服务的好方法。让我们希望 Concepts 有一天能够实现这一目标......!

As you've noted, there's nothing in the usage of sort_ints that hints at its requirements of the comparison functor:

compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);

There's nothing in sort_ints itself either:

template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);

And in class_compare, we can only deduce the functionality that will be used by observing it offers no other functionality:

class compare_class
{
  public:
     bool operator()(int A, int B) const { return A < B; }
};

The compiler does indeed leave it until it tries to compile the implementation of sort_ints, using the types with which it's instantiated, before it works out whether this all hangs together. sort_ints will have to have exactly the kind of statement you mention:

c(*begin_items, *(begin_items+1));    // note: functor argument is "c"

So, your understanding is correct on all counts. BUT, it's worth noting that the proposed C++0x feature called Concepts was intended to make the requirements of sort_int more explicit without looking at its implementation. Unfortunately, C++0x had to abandon this feature as there's been insufficient time and experience to ensure it's optimal. Hopefully a future version of C++ will incorporate such a feature. You can find lots of discussions of Concepts on the 'net, and they should help you understand the overall issue better.

It's an important issue because when you've only pieces of the puzzle - such as a sort_ints function you want to use but no example ComparisonFunctor, then you have to study the implementation of sort_ints to know how to create that Functor (unless you're super lucky and there's good, current documentation). You may accidentally make your code too dependent on the existing implementation, so that your code breaks or slows down unacceptably when the implementation of sort_int is changed slightly later - even if it is subtly enough not to break the test cases or other users' code or expectations. It's also likely that a small mistake in the provided ComparisonFunctor will produce a very convoluted and confusing compiler error message from somewhere in the guts of sort_int - that's not a nice way to provide a user with an abstracted service. Let's hope Concepts makes it in one day...!

戴着白色围巾的女孩 2024-10-21 19:22:47

请注意,compare_class 是一个类。因此它可以像使用其他类一样被声明、作为函数参数传递。

其次,compare_class实现了operator()。这允许您执行以下操作:

compare_class obj;
obj(1, 2);

现在,上面代码片段中的第二个语句看起来像一个函数调用!因此从某种意义上说,任何实现了operator()的类的对象都可以像函数一样使用。

这就是函数对象的要点。此外,与函数指针相比​​,它还有其他优点,您可以在帖子中给出的同一链接中找到这些优点。

编辑

sort_ints()内,仿函数预计会执行如下操作:

for (int i = 1; i < num_items; i++)
    if (c(begin_items[i-1], begin_items[i]))
    {
        // begin_items[i-1] is less than begin_items[i], do stuff
    }

Notice that, compare_class is a class. So it can be declared, passed as function parameter the way you use other classes.

Secondly, compare_class implementes operator(). This allows you to do the following:

compare_class obj;
obj(1, 2);

Now, the second statement in the above code fragment seems like a function call! So in a sense, any object of a class that implements operator() can be use like a function.

That's the point of function objects. Besides, it has other advantages over function pointers which you will find in the same link you've given in your post.

EDIT

Inside sort_ints(), functor is expected to do something like the following:

for (int i = 1; i < num_items; i++)
    if (c(begin_items[i-1], begin_items[i]))
    {
        // begin_items[i-1] is less than begin_items[i], do stuff
    }
清晰传感 2024-10-21 19:22:47

是的,这是正确的。函数调用运算符应用于对象的名称,而不是对象的方法。此外,您根本没有传递函数的地址,而是传递(复制)一个对象。仿函数对象没有数据成员,只有一个运算符 ( )。

Yes, that's correct. The function call operator is applied to the name of the object, not a method of the object. Furthermore, you are not passing an address of a function at all, you are passing (copying) an object. functor objects have no data members, only an operator ( ).

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