简体   繁体   English

就地构造std :: function目标

[英]Constructing std::function target in-place

What I understand as a typical use of 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;
}

yields following output 产量跟随输出

CREATING
MOVE C
DELETING
CALLING
DELETING

Apparently, temporary object is created on stack and then moved into function object. 显然,临时对象是在堆栈上创建的,然后移动到函数对象中。 If move constructor is not provided, it is copied instead. 如果未提供move构造函数,则会复制它。
Is there a standard way of setting the target without need for a temporary object? 是否有标准的方法来设置目标而不需要临时对象?

The way that function is constructed from any functor F f is stipulated by the standard in §20.9.11.2.1 as (assuming f is a non-null, emphasis mine): 从任何仿函数F f构造function的方式由§20.9.11.2.1中的标准规定为(假设f是非空的,强调我的):

*this targets a copy of f initialized with std::move(f) *this目标是使用std::move(f)初始化的f副本

So there is no way to in-place construct a function . 因此无法就地构建function That leaves you with a choice between incurring that move: 这让你可以选择招致这一举动:

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

Or passing in some wrapper around C that is cheaper to move/copy, either one in which you manage externally: 或者在C周围传递一些更便宜的移动/复制包装,你可以在其中进行外部管理:

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

... or an allocated one bound to operator() : ...或绑定到operator()已分配的:

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

That last one could cause some headaches if operator() happens to be overloaded, as you'd have to cast it to the right type, which is an issue that none of the previous versions have to deal with. 如果operator()恰好被重载,那最后一个可能会引起一些麻烦,因为你必须将它强制转换为正确的类型,这是以前版本都没有处理的问题。

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

You can use std::bind but you do not really need to implement operator() for that: 你可以使用std::bind但是你真的不需要为它实现operator()

int main(int argc, char *argv[]) {
    C c;
    function<void()> f = std::bind( &C::operator(), &c );
    f();
    return 0;
}

output: 输出:

CREATING
CALLING
DELETING

of course you need to properly maintain lifetime of object c in this case. 当然,在这种情况下,您需要正确维护对象c的生命周期。 To make std::function to own C instance and make it more in-place construction std::shared_ptr can be used: 要使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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM