C++ Return 仿函数对象 std::function
C++ Return a functor object as std::function
我有一个工厂方法 returning std::function
class Builder {
public:
function<void(Data&)> build();
}
和一个函子对象
class Processor {
protected:
vector<int> content_;
public:
void operator()(Data&) {
....
}
}
现在我要return工厂方法中的仿函数,我写
function<void(Data&)> build() {
Processor p;
// Add items to p.content_
function<void(Data&)> ret(p);
return ret;
}
我的问题是:ret
会维护 p
的副本吗?如果是这样,当 p.content_
很大时,那会不会成为负担?实施此建议的方法是什么?
一个std::function
持有并拥有它的价值。事实上,它需要可复制的可调用对象,以便在复制自身时复制它。
你的函数会像这样非常好,而且可能更快:
function<void(Data&)> build() {
Processor p;
// fill items
return p; // p moved into the returned std::function (since C++14)
}
然而,如果你复制 std::function
周围,Processor
对象也会被复制,所以复制 std::function
的成本取决于它包含的类型(就像使用任何类型的擦除工具)
将使用的构造函数是this:
template< class F >
function( F f );
您可以看到对象将被复制。如果你想避免这种情况,你可以移动 callable:
function<void(Data&)> ret(std::move(p));
构造函数然后将 f
移动到内部存储。
如果你的可调用对象很小,它会直接存储在函数对象中。如果太大,内部存储将被动态分配。无论哪种方式,移动结果函数对象应该不会比移动原始可调用对象(当直接存储在函数中时)复杂,甚至可能更便宜(当动态存储时)。
当性能很重要时应避免复制,因为它可能涉及动态分配,即使您的可调用对象不需要它们。
我有一个工厂方法 returning std::function
class Builder {
public:
function<void(Data&)> build();
}
和一个函子对象
class Processor {
protected:
vector<int> content_;
public:
void operator()(Data&) {
....
}
}
现在我要return工厂方法中的仿函数,我写
function<void(Data&)> build() {
Processor p;
// Add items to p.content_
function<void(Data&)> ret(p);
return ret;
}
我的问题是:ret
会维护 p
的副本吗?如果是这样,当 p.content_
很大时,那会不会成为负担?实施此建议的方法是什么?
一个std::function
持有并拥有它的价值。事实上,它需要可复制的可调用对象,以便在复制自身时复制它。
你的函数会像这样非常好,而且可能更快:
function<void(Data&)> build() {
Processor p;
// fill items
return p; // p moved into the returned std::function (since C++14)
}
然而,如果你复制 std::function
周围,Processor
对象也会被复制,所以复制 std::function
的成本取决于它包含的类型(就像使用任何类型的擦除工具)
将使用的构造函数是this:
template< class F >
function( F f );
您可以看到对象将被复制。如果你想避免这种情况,你可以移动 callable:
function<void(Data&)> ret(std::move(p));
构造函数然后将 f
移动到内部存储。
如果你的可调用对象很小,它会直接存储在函数对象中。如果太大,内部存储将被动态分配。无论哪种方式,移动结果函数对象应该不会比移动原始可调用对象(当直接存储在函数中时)复杂,甚至可能更便宜(当动态存储时)。
当性能很重要时应避免复制,因为它可能涉及动态分配,即使您的可调用对象不需要它们。