就地构造std :: function目标

时间:2015-01-14 22:06:30

标签: c++ c++11 std-function

我理解为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

显然,临时对象是在堆栈上创建的,然后移动到函数对象中。如果未提供移动构造函数,则会复制它 是否有标准的方法来设置目标而不需要临时对象?

2 个答案:

答案 0 :(得分:5)

function从任何仿函数F f构造的方式由§20.9.11.2.1中的标准规定为(假设f是非空的,强调我的) :

  

*this定位使用 f

初始化的std::move(f) 副本

因此无法就地构建function。这让你可以选择招致这一举动:

function<void()> f1 = C{};

或传递一些更便宜的移动/复制C包装,或者你在外部管理的包装:

C manage_me;
function<void()> f2 = std::ref(manage_me);

...或绑定到operator()的已分配的一个:

function<void()> f3 = std::bind(&C::operator(), std::make_shared<C>());

如果operator()碰巧被重载,最后一个可能会引起一些麻烦,因为你必须将它强制转换为正确的类型,这是以前版本都没有处理的问题。 / p>

function<void()> f4 = std::bind(
                          static_cast<void(C::*)()>(&C::operator()),
                          std::make_shared<C>()
                          );

答案 1 :(得分:4)

您可以使用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;
}