我有一个std :: functions
的向量Using Functors = std::vector<std::function<bool(int)>>;
Functors fs;
现在,如果我想向向量添加一个函数,我会这样做:
fs.emplace_back(
[](int v)->bool { return v > 1; }
)
我想知道当我声明“Functors”时,我应该指向std :: function而不是raw std :: function吗?这意味着,我将这样声明:
Using Functors = std::vector<
std::function<bool(int)>*
>; // note the last &
因此,当我调用emplace_back时,我只会传入指针而不是复制?或者lambda闭合可以移动?请在这里说明一下:我何时应该使用std :: function?
的引用答案 0 :(得分:7)
只需使用std::vector<std::function<bool(int)>>
。
std::function
几乎总是便宜。
为了不便宜,存储的函数对象必须(A)小,(B)有一个no-except移动构造函数,(C)移动成本很高。
有意识地写这样的对象并不困难,但很难不小心写一个 。
现在,标准没有规定多小;对于MSVC,他们将其设置为一个或两个std::string
的大小,作为示例。
管理原始指针的开销几乎肯定会使你的代码比使用这里的值更差,性能更差。两者都是因为你正在燃烧精神资源来修复原始指针错误,并且因为在免费商店中分配对象比std::function
几乎任何类型移动几个数量级时都要贵。
平均而言,std::vector
中的元素将被移动恒定次数(通常为1-3),如果您使用push_back
填充空白的向量,因为内存管理的强制增长指数地,只有在需要调整大小时才会移动对象。
拥抱价值语义。
答案 1 :(得分:1)
首先,引用不能是模板的参数类型,因此您需要使用指针或std::reference_wrapper
代替:
std::vector<std::function<bool(int)>*>
std::vector<std::reference_wrapper<std::function<bool(int)>>>
在您的示例中,您的向量将无法保存对函数的“引用”,因为您在r值上调用emplace_back
。所以在这里,std::vector<std::function<bool(int)>>
似乎是一个很好的解决方案。
答案 2 :(得分:1)
简而言之:从不!
(至少在你谈论std::function<...>*
时没有 - 见下文)
如果你真的只想存储函数,请创建一个函数指针向量:
std::vector<bool(*)(int)> fs;
这也适用于示例中带有空捕获的lambdas,因为它们隐式转换为函数指针。
如果你想存储任意能力的对象,{99}的时间std::vector<std::function<bool(int)>>;
应该没问题。这很简单,你不太可能犯任何错误和最节省空间的解决方案。
如果你真的想出于某种原因在堆上创建std :: function对象,那么使用unique_ptr:
std::vector<std::unique_ptr< std::function<bool(int)> >> fs;
fs.push_back( std::make_unique< std::function<bool(int)> >( [](int){ return true;}) );
这将确保您不会忘记删除这些对象。
<强>解释强>
也许我错了,但在我看来好像你对std::function
是什么有误解。它不是表示本机函数的类,而是一个(相当繁重的)类,它可以包装任何可调用的函数(函数,函数对象,指向成员函数的指针 - 甚至指向成员的指针)。
std::function
的间接增加了显着的开销(它们通常是大小的指针,移动/复制是实际的功能),但它仍然是安全的。 std::function
通常需要在堆上创建该对象,这需要额外的开销,但至少移动再次便宜。然而,它伴随着原始拥有指针的通常问题。因此,std::unique_ptr
的解决方案。