【发布时间】:2013-01-31 12:09:31
【问题描述】:
我想创建一个带有自定义比较功能的std::set。我可以用operator() 将它定义为一个类,但我想享受定义一个使用它的 lambda 的能力,所以我决定在具有 @ 的类的构造函数的初始化列表中定义 lambda 函数987654323@ 成为会员。但我无法获得 lambda 的类型。在我继续之前,这里有一个例子:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
我搜索后发现了两种解决方案:一种,使用std::function。只需将设置比较函数类型设为std::function<bool (int, int)> 并像我一样传递 lambda。第二种方案是写一个make_set函数,比如std::make_pair。
解决方案 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
解决方案 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
问题是,我是否有充分的理由偏爱一种解决方案而不是另一种?我更喜欢第一个,因为它使用标准功能(make_set 不是标准功能),但我想知道:使用std::function 是否会使代码(可能)变慢?我的意思是,它是否会降低编译器内联比较函数的机会,或者它应该足够聪明,以至于它的行为与它是一个 lambda 函数类型而不是std::function 完全相同(我知道,在这种情况下它可以'不是 lambda 类型,但你知道,我问的是一般情况)?
(我使用 GCC,但我想知道流行的编译器一般都做什么)
总结,在我得到很多很好的答案之后:
如果速度很关键,最好的解决方案是使用带有operator() aka functor 的类。编译器最容易优化和避免任何间接。
为了便于维护和更好的通用解决方案,使用 C++11 功能,请使用std::function。它仍然很快(只是比仿函数慢一点,但可以忽略不计)并且您可以使用任何函数 - std::function、lambda、任何可调用对象。
还有一个使用函数指针的选项,但如果没有速度问题,我认为std::function 更好(如果你使用 C++11)。
有一个选项可以在其他地方定义 lambda 函数,但是如果比较函数是 lambda 表达式,您将一无所获,因为您也可以使用 operator() 将其设为一个类,并且定义的位置不会是无论如何设置构造。
还有更多的想法,比如使用委托。如果您想更全面地解释所有解决方案,请阅读答案:)
【问题讨论】:
-
我闻到过早的优化。
-
为什么不只是
bool(*)(int, int)?但是创建一个显式的、可默认构造的谓词类可能更有效。 -
@Fanael 你怎么知道,如果我有一长串由 GUI 渲染的对象,我真的需要它尽可能快
-
@fr33domlover:在这种情况下,
std::function的成本与渲染成本相比是不是相形见绌? -
@Fanael 如果在没有渲染的情况下完成排序,我仍然可以通过加快排序并为渲染代码提供更多执行时间来获得更快的速度。无论如何,即使如果这是过早的优化,问题仍然有用:查看答案并点赞...
标签: c++ stl c++11 lambda std-function