В приведенном ниже коде я хочу use_count()
из shared_ptr
переехал в std::async
быть 1
:
#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?
возможный обходной путь может быть
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 делает дополнительную копию в исходном коде; кажется, что временное значение, данное decay_copy в async (), не передается параметру fun () в качестве значения r, как должно быть. Разве вы не можете войти со своим отладчиком, чтобы увидеть, что происходит?
Хотя std::async
создает копии всех аргументов, при вызове функции она перенаправляет аргументы в вызываемый объект, так что категория значения аргумента сохраняется.
Аргументы std::async
должны быть только MoveConstructible, в противном случае было бы невозможно пройти std::unique_ptr
в std::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();
}