就地构建 std::function 目标
Constructing std::function target in-place
我所理解的 std::function
的典型用法
#include <iostream>
#include <functional>
using namespace std;
class C {
public:
C() { cout << "CREATING" << endl; }
C(const C&) { cout << "COPY C "<< endl; };
C(C&&) { cout << "MOVE C " << endl; };
~C() { cout << "DELETING"<< endl; }
C& operator =(const C&) {
cout << "COPY A " << endl; return *this;
};
C& operator =(C&&) {
cout << "MOVE A" << endl; return *this;
};
void operator ()() const { cout << "CALLING" << endl; }
};
int main(int argc, char *argv[]) {
function<void()> f = C();
f();
return 0;
}
产量跟随输出
CREATING
MOVE C
DELETING
CALLING
DELETING
显然,临时对象是在堆栈上创建的,然后移动到函数对象中。如果未提供移动构造函数,则会复制它。
是否有无需临时对象即可设置目标的标准方法?
您可以使用 std::bind
,但实际上并不需要为此实施 operator()
:
int main(int argc, char *argv[]) {
C c;
function<void()> f = std::bind( &C::operator(), &c );
f();
return 0;
}
输出:
CREATING
CALLING
DELETING
在这种情况下,您当然需要正确维护对象 c 的生命周期。
要使 std::function
拥有 C
实例并使其更加就地构造 std::shared_ptr
可以使用:
int main(int argc, char *argv[]) {
function<void()> f = std::bind( &C::operator(), std::make_shared<C>() );
f();
return 0;
}
从任何函子 F f
构造 function
的方式由 §20.9.11.2.1 中的标准规定为(假设 f
是非空的,强调我的):
*this
targets a copy of f
initialized with std::move(f)
因此无法就地构建 function
。这让您可以选择是否采取行动:
function<void()> f1 = C{};
或者在 C
周围传递一些比 move/copy 更便宜的包装器,您可以在其中进行外部管理:
C manage_me;
function<void()> f2 = std::ref(manage_me);
... 或分配给 operator()
:
function<void()> f3 = std::bind(&C::operator(), std::make_shared<C>());
如果 operator()
碰巧超载,最后一个可能会引起一些麻烦,因为您必须将其转换为正确的类型,这是 none 以前版本的问题必须处理。
function<void()> f4 = std::bind(
static_cast<void(C::*)()>(&C::operator()),
std::make_shared<C>()
);
我所理解的 std::function
#include <iostream>
#include <functional>
using namespace std;
class C {
public:
C() { cout << "CREATING" << endl; }
C(const C&) { cout << "COPY C "<< endl; };
C(C&&) { cout << "MOVE C " << endl; };
~C() { cout << "DELETING"<< endl; }
C& operator =(const C&) {
cout << "COPY A " << endl; return *this;
};
C& operator =(C&&) {
cout << "MOVE A" << endl; return *this;
};
void operator ()() const { cout << "CALLING" << endl; }
};
int main(int argc, char *argv[]) {
function<void()> f = C();
f();
return 0;
}
产量跟随输出
CREATING
MOVE C
DELETING
CALLING
DELETING
显然,临时对象是在堆栈上创建的,然后移动到函数对象中。如果未提供移动构造函数,则会复制它。
是否有无需临时对象即可设置目标的标准方法?
您可以使用 std::bind
,但实际上并不需要为此实施 operator()
:
int main(int argc, char *argv[]) {
C c;
function<void()> f = std::bind( &C::operator(), &c );
f();
return 0;
}
输出:
CREATING
CALLING
DELETING
在这种情况下,您当然需要正确维护对象 c 的生命周期。
要使 std::function
拥有 C
实例并使其更加就地构造 std::shared_ptr
可以使用:
int main(int argc, char *argv[]) {
function<void()> f = std::bind( &C::operator(), std::make_shared<C>() );
f();
return 0;
}
从任何函子 F f
构造 function
的方式由 §20.9.11.2.1 中的标准规定为(假设 f
是非空的,强调我的):
*this
targets a copy off
initialized withstd::move(f)
因此无法就地构建 function
。这让您可以选择是否采取行动:
function<void()> f1 = C{};
或者在 C
周围传递一些比 move/copy 更便宜的包装器,您可以在其中进行外部管理:
C manage_me;
function<void()> f2 = std::ref(manage_me);
... 或分配给 operator()
:
function<void()> f3 = std::bind(&C::operator(), std::make_shared<C>());
如果 operator()
碰巧超载,最后一个可能会引起一些麻烦,因为您必须将其转换为正确的类型,这是 none 以前版本的问题必须处理。
function<void()> f4 = std::bind(
static_cast<void(C::*)()>(&C::operator()),
std::make_shared<C>()
);