gpt4 book ai didi

c++ - 仿函数与 std::bind

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:07:22 25 4
gpt4 key购买 nike

有时我倾向于编写仿函数,不是为了维护函数调用之间的状态,而是因为我想捕获一些函数调用之间共享的参数。例如:

class SuperComplexAlgorithm
{
public:
SuperComplexAlgorithm( unsigned int x, unsigned int y, unsigned int z )
: x_( x ), y_( y ), z_( z )
{}

unsigned int operator()( unsigned int arg ) const /* yes, const! */
{
return x_ * arg * arg + y_ * arg + z_;
}

private:
// Lots of parameters are stored as member variables.
unsigned int x_, y_, z_;
};

// At the call site:
SuperComplexAlgorithm a( 3, 4, 5 );
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a ); // or whatever

相比于

unsigned int superComplexAlgorithm( unsigned int x, unsigned int y,
unsigned int z, unsigned int arg )
{
return x * arg * arg + y * arg + z;
}

// At the call site:
auto a = std::bind( superComplexAlgorithm, 3, 4, 5, std::placeholders::_1 );
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a );

在我看来,第一个解决方案有很多缺点:

  • xyz 所做的文档被拆分在不同的地方(构造函数、类定义、operator() ).
  • 大量样板代码。
  • 不太灵活。如果我想捕获不同的参数子集怎么办?

是的,我刚刚意识到 boost::bindstd::bind 有多么有用。在我开始在我的很多代码中使用它之前,现在问我的问题:在任何情况下我应该考虑使用手写的无状态仿函数而不是在普通函数中绑定(bind)参数?

最佳答案

lambda 解决方案将是惯用的 C++11 方式:

auto a = [&]( int x ){ return superComplexAlgorithm( 3, 4, 5, x ); };
for( unsigned int i = 0; i < 100; ++i )
do_stuff_with( a );

使用手写仿函数的优点是您可以:

  1. 将参数移动到捕获中,或转换它们(您可以使用 C++1y 中的 lambda 执行此操作,但现在还不能——这也可以使用 bind)
  2. 它有一个非匿名类型(所以你可以在不使用auto的情况下谈论类型)——bind也是如此,但它也有一个无需decltype 整个表达式即可获得非匿名有意义 类型! C++1y 再次使 bind/lambda 变得更好。
  3. 您可以完美转发剩余的参数(您可以在 C++1y 中使用 lambda 执行此操作,bind 可以执行此操作)
  4. 您可以弄乱捕获数据的存储方式(在指针中?智能指针?),而不会弄乱创建实例的代码。

你还可以用手写的仿函数做一些用 bind 和 lambdas 不可能做的非常强大的事情,比如将多个函数的重载集包装到一个对象中(可能共享也可能不共享一个名字),但这种极端情况不会经常出现。

关于c++ - 仿函数与 std::bind,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17810018/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com