在原地构造std::function目标

5

我理解的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个回答

5
从任何函子F f构建function的方式在标准§20.9.11.2.1中规定为(假设f是非空的,强调是我的):

*this指向使用std::move(f)初始化的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() 发生重载,最后一个可能会带来一些麻烦,因为您需要将其转换为正确的类型,这是之前版本都不必处理的问题。

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

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;
}

1
如果他在进行'C()',那么对象的范围无论如何都会受到限制。 - user3920237
当然,这并不是利用原地构造,而是根本没有构造。但仍然值得一提,可能在某些情况下会有用。 - 5gon12eder
1
好的,在函数对象内部不进行构造。;-) - 5gon12eder
@5gon12eder 好观点,已添加就地构建示例。 - Slava
那个最新版本非常有趣。(说实话,我有点惊讶它能工作。)如果我们担心复制函数对象的成本很高,那么std::function可能已经分配了内存,因此假设共享指针足够小,使得std::function利用其小对象优化,我们可以在自由存储器上创建函数对象,而不会增加额外的成本。 - 5gon12eder
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接