函数对象与状态

Function Objects vs State

本文关键字:状态 对象 函数      更新时间:2023-10-16

我使用函数对象来找出传递的对象会发生什么,以及它如何影响对象的状态。下面是测试代码的片段:

#include <iostream>
//#include <boost/function.hpp>
//using boost::function;
#include <functional>
using std::function;
using std::bind;
struct A {
  A() { std::cout << "Creating..." << "n"; }
  void operator()() { call(); }
  void call() { std::cout << "Executing call..." << "n"; }
  virtual ~A() { std::cout << "Destroying" << "n"; }
};
typedef function<void ()> Func;
struct B{
  Func f;
  B(Func ff) : f(ff) {}
  void call() {f();}
};
int main(int argc, char *argv[])
{
  {
    A a;
    B b(a);
    for (int i = 0; i < 5; ++i)
      b.call();
  }
  {
    A a2;
    B b2(bind(&A::call, &a2));
    for (int i = 0; i < 5; ++i)
      b2.call();
  }
  return 0;
}
/** Output **
  Creating...
  Destroying
  Destroying
  Executing call...
  Executing call...
  Executing call...
  Executing call...
  Executing call...
  Destroying
  Destroying
  Creating...
  Executing call...
  Executing call...
  Executing call...
  Executing call...
  Executing call...
  Destroying
 */

当我使用运算符 (( 重载传递对象时,有一些对析构函数的多次调用;并且没有创建任何对象!所以,我不能依赖,可以这么说,对象状态的保真度。这是否意味着当我传递一个函数对象(带有重载运算符(((进行回调时,我应该假设对象的状态没有保留?这是预期的行为吗?

另一方面,从另一种类型的对象内部回调绑定成员函数会产生非常稳定的行为(我不知道使用什么术语(;也就是说,我希望对象状态得到保留;确实如此!这也是有意的行为吗?IOW,这是通常理解函子的方式吗?

附注:

我还用boost::

function和boost::bind ---检查了它,结果非常相似。可能需要另一个线程来讨论细微差别。

关于"无构造函数":有对复制构造函数的调用。

尝试更多仪器:

struct A {
  A() { std::cout << "Creating..." << "n"; }
  void operator()() { call(); }
  A(const A&) { std::cout << "Copying" << "n"; }
  A(A&&) { std::cout << "Moving" << "n"; } // Assuming C++11
  void call() { std::cout << "Executing call..." << "n"; }
  virtual ~A() { std::cout << "Destroying" << "n"; }
};  

关于复制:

  • 您将可调用的 by 值交给 B 的构造函数。它必须被复制。
  • 绑定,如果您提交值,这是预期的行为。您交给绑定的可调用对象可能是临时的。因此,默认行为是复制。

如果您知道可调用对象将存活足够长的时间(就像代码中的情况一样(,则可以通过使用引用包装器来避免这种情况。尝试:

int main(int argc, char *argv[])
{
  {
    A a;
    {
      B b(a);
    }
    std::cout << "-------------n";
    B(std::ref(a));
    std::cout << "-------------n";
    B(bind(&A::call, a));
    std::cout << "-------------n";
    B(bind(&A::call, &a));
    std::cout << "-------------n";
    B(bind(&A::call, std::ref(a)));
    std::cout << "-------------n";
  }
  std::cout << "-------------n";
  return 0;
}

当我使用运算符 (( 重载传递对象时,有一些对析构函数的多次调用;并且没有创建任何对象!

您不计算使用复制构造函数构造的对象,该构造函数由编译器在您不提供任何对象时创建。

将复制构造函数添加到A您将看到对析构函数的调用次数与对构造函数的调用次数相同。

struct A {
  A() { std::cout << "Creating..." << "n"; }
  // Add this
  A(A const& copy) { std::cout << "Creating..." << "n"; }
  void operator()() { call(); }
  void call() { std::cout << "Executing call..." << "n"; }
  virtual ~A() { std::cout << "Destroying" << "n"; }
};