2

在下面的代码中,我希望移入use_count()的是:shared_ptrstd::async1

#include <memory>
#include <iostream> 
#include <future> 

using namespace std;

void fun(shared_ptr<int> sp)
{
    cout << "fun: sp.use_count() == " << sp.use_count() <<
        " (in gcc 4.6.3, is there a way to make this 1?)\n";
}

int main()
{
    auto sp1 = make_shared<int>(5);

    auto fut = async(
        launch::async,
        fun,
        move(sp1)
    );
}

我的平台使用 gcc 4.6.3,上面的代码给出了这个输出(fun: sp.use_count() == 2):

fun: sp.use_count() == 2 (in gcc 4.6.3, is there a way to make this 1?)

coliru.stacked-crooked.com 上,我得到了我想要的行为(fun: sp.use_count() == 1):

fun: sp.use_count() == 1 (in gcc 4.6.3, is there a way to make this 1?)

我不确定 coliru 使用的是什么编译器,但我猜它比 gcc 4.6.3 更新。

是否有某种方法,一些解决方法,可以获得我想要的行为,而不必从 gcc 4.6.3 升级我的编译器?

4

2 回答 2

1

一个可能的解决方法可能是

void fun(shared_ptr<int>* sp)
{
    unique_ptr<shared_ptr<int>> guard(sp);

    cout << "fun: sp.use_count() == " << sp->use_count() <<
        " (in gcc 4.6.3, is there a way to make this 1?)\n";
}

int main()
{
    auto sp1 = make_shared<int>(5);

    auto fut = async(
        launch::async,
        fun,
        new shared_ptr<int>(move(sp1))
    );
}

也就是说,看看 gcc463 在原始代码中在哪里制作了额外的副本会很有趣;似乎 async() 中由 decay_copy 给出的临时值没有像应该的那样作为右值转发给 fun() 的参数。你不能用你的调试器来看看发生了什么吗?

于 2017-11-01T16:59:23.263 回答
0

尽管std::async会复制所有参数,但在调用该函数时,它会将参数完美转发到可调用对象,以便保留参数值类别。

to 的参数std::async只需要是MoveConstructible,否则将无法传递std::unique_ptrstd::async

换句话说,正确的行为是sp.use_count() == 1,这是我用旧的 g++-5.3.1 观察到的。


检查以下代码是否与您观察到的编译器一起编译sp.use_count() == 2

using namespace std;

void fun(unique_ptr<int> p) {
    cout << "fun " << *p << '\n';
}

int main() {
    unique_ptr<int> sp(new int{1});

    auto fut = async(
        launch::async,
        fun,
        move(sp)
    );

    fut.get();
}
于 2017-11-01T15:43:13.323 回答