0

我有一个 C++ 类,它的一个字段是 std::set 对象。我想自己写一个比较函数,或者让用户指定一个。在 C++11 中有一种处理泛型函数类型的新方法:std::function。它适用于函数指针、成员函数指针、lambda 函数等。

我尝试编写一个简单的实验程序,但它一直在卡顿,即使我按照 C++11 维基百科文章的建议进行操作。也许我只是不明白应该如何使用 std::function 和 std::ref 。

无论如何,关键是当我从一个简单的 lambda 函数创建一个 std::function 并使其成为类成员时,该类的 sizeof 增长了 22。当我从一个指向全局函数的指针创建一个 std::function 时,这个 std::function 的 sizeof 是 32。所以大小很大。我将有许多对象使用相同的比较函数,所以我更喜欢让所有对象都使用一个函数。

我有两个想法,告诉我你的想法。一个想法,使用 std::ref 存储对函数的引用,这样我可以定义一个函数,许多对象将使用它来比较 std::set 元素。第二个想法:如果它不能那样工作,或者生成的函数对象太大,也许我可以使用 shared_ptr。

您可能想知道:为什么没有一个静态 std::function 成员?答案是:因为所有对象都将使用相同的比较函数。例如,我希望能够拥有 1000 个对象,其中 400 个使用一个比较函数,600 个使用不同的比较函数。

例子:

class MyClass
{
public:
private:
     std::function<bool (int, int)> compare;
     std::set<int> set;
};

现在如何让 std::set 使用 std::function,并让许多 MyClass 对象使用相同的函数?

我希望能够在运行时更改比较功能,以便用户能够选择集合中对象的顺序(由 GUI 显示)。

4

2 回答 2

2

表示共享所有权的标准方法是使用std::shared_ptr. 这会增加一些开销,迫使您std::function在堆上分配 ,但是 ashared_ptr小于 astd::function并且它将正确管理其生命周期,因此当任何对象仍在使用函数对象时,它将保持活动状态并自动销毁不再需要。

正如您所建议的,reference_wrapper引用共享函数的 a 可以用作set的比较对象,因为reference_wrapper如果 a 包装了可调用类型,则它是可调用的。

class MyClass
{
     typedef std::function<bool (int, int)> func_type;
public:
     MyClass(std::shared_ptr<func_type> const& f)
     : compare(f), set( std::ref(*f) )
     { }
private:
     std::shared_ptr<func_type> compare;
     std::set<int, std::reference_wrapper<func_type>> set;
};

Areference_wrapper不能为空(如引用),因此您必须std::set使用有效reference_wrapper对象构造 。

由于std::reference_wrapperinstd::set只是持有指向 的非拥有指针,因此std::function您需要在更新 的同时小心更新集合的比较对象shared_ptr,或者您可以删除对该函数的最后一个引用,因此shared_ptr会破坏它,在集合中留下一个悬空指针。可以这样做:

void MyClass::replace_cmp(std::shared_ptr<func_type> const& f)
{
  set = std::set<int, std::reference_wrapper<func_type>>( std::ref(*f) );
  compare = f;
}
于 2013-02-15T11:27:02.077 回答
2

你告诉集合在你的构造函数初始化列表中使用你的比较函数:

class MyClass
{
public:
    template<typename Fc>
    MyClass(Fc compare_func)
        : compare(compare_func),  // Initialize the comparison function
          set(compare)            // Tell the set to use out function for comparison
        {}
};
于 2013-02-15T11:36:53.000 回答