为什么我不能在std :: future参数中使用reference

Fro*_*art 7 c++ c++11 c++14

为什么下面的代码(在Ideone上)给我一个错误?

#include <future>
#include <iostream>
#include <string>

int main()
{
    int foo = 0;
    bool bar = false;
    std::future<std::string> async_request = std::async(
        std::launch::async,
        [=, &foo](bool& is_pumping_request) -> std::string {
            return "str";
        },
        bar
    );
    std::cout << async_request.get() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出:

In file included from /usr/include/c++/5/future:38:0,
                 from prog.cpp:1:
/usr/include/c++/5/functional: In instantiation of 'struct std::_Bind_simple<main()::<lambda(bool&)>(bool)>':
/usr/include/c++/5/future:1709:67:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = main()::<lambda(bool&)>; _Args = {bool&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = std::basic_string<char>]'
prog.cpp:15:2:   required from here
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<main()::<lambda(bool&)>(bool)>'
         _M_invoke(_Index_tuple<_Indices...>)
         ^
Run Code Online (Sandbox Code Playgroud)

不过,如果我更改bool&bool在参数列表中,它编译成功.

为什么?

Nat*_*ica 13

比如std::thread,std::asyc将参数按值传递给"函数".如果你有一个函数,它引用你需要用你传递给变量asycstd::ref

#include <future>
#include <iostream>
#include <string>

int main()
{
    int foo = 0;
    bool bar = false;
    std::future<std::string> async_request = std::async(
        std::launch::async,
        [=, &foo](bool& is_pumping_request) -> std::string {
            return "str";
        },
        std::ref(bar)
    );
    std::cout << async_request.get() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

Live Example

如果函数需要使用,const &则需要使用std::cref.


Yak*_*ont 8

考虑如果它bar通过引用绑定会发生什么.

然后每次调用时std::async,您传递的每个值都必须持续到异步完成.

这将是意外记忆腐败的一个秘诀.因此,std::async默认情况下会复制您传递给它的所有内容.

然后它会在输入的副本上运行任务.

聪明,它通过将代码移动到代码中来告诉您调用的代码是非持久性的.并且左值引用无法绑定到移动值.

您可以使用覆盖此行为std::reference_wrapper. async理解reference_wrapper,并自动存储对这些值的引用,并通过引用将它们传递给被调用的代码.

创建a的简单方法reference_wrapper是调用std::ref.

int foo = 0;
bool bar = false;
std::future<std::string> async_request = std::async(
    std::launch::async,
    [=, &foo](bool& is_pumping_request) -> std::string {
        return "str";
    },
    std::ref(bar)
);
std::cout << async_request.get() << std::endl;
Run Code Online (Sandbox Code Playgroud)

它只是有效.

这种"仅通过引用明确地传递"是类似绑定操作的安全特征; 因为绑定执行可以持续超出当前状态,所以它要求调用者仅通过引用明确绑定,从而减少意外悬空引用的机会.