実際、あなたが与えた例は、次のようなかなり長い関数を使用した場合の違いを示しています
//! sleeps for one second and returns 1
auto sleep = [](){
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 1;
};
パッケージ化されたタスク
Apackaged_taskは単独では起動しません。呼び出す必要があります。
std::packaged_task<int()> task(sleep);
auto f = task.get_future();
task(); // invoke the function
// You have to wait until task returns. Since task calls sleep
// you will have to wait at least 1 second.
std::cout << "You can see this after 1 second\n";
// However, f.get() will be available, since task has already finished.
std::cout << f.get() << std::endl;
std::async
一方、std::asyncwithlaunch::asyncは別のスレッドでタスクを実行しようとします:
auto f = std::async(std::launch::async, sleep);
std::cout << "You can see this immediately!\n";
// However, the value of the future will be available after sleep has finished
// so f.get() can block up to 1 second.
std::cout << f.get() << "This will be shown after a second!\n";
欠点
しかしasync、すべてに使用しようとする前に、返された Future には特別な共有状態があることを覚えておいてください。これはfuture::~futureブロックを要求します:
std::async(do_work1); // ~future blocks
std::async(do_work2); // ~future blocks
/* output: (assuming that do_work* log their progress)
    do_work1() started;
    do_work1() stopped;
    do_work2() started;
    do_work2() stopped;
*/
したがって、実際の非同期が必要な場合は、返された を保持する必要がありますfuture。または、状況が変化した場合に結果を気にしない場合:
{
    auto pizza = std::async(get_pizza);
    /* ... */
    if(need_to_go)
        return;          // ~future will block
    else
       eat(pizza.get());
}   
詳細については、問題について説明しているHerb Sutterの記事asyncと~futureを参照してください。また、この動作は C++14 以降で指定されていましたが、C++11 でも一般的に実装されていることに注意してください。std::futuresstd::async
その他の違い
を使用すると、他のスレッドに移動できるstd::async特定のスレッドでタスクを実行できなくなります。std::packaged_task
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::thread myThread(std::move(task),2,3);
std::cout << f.get() << "\n";
また、packaged_taskを呼び出す前に a を呼び出す必要がありますf.get()。そうしないと、future の準備ができていないため、プログラムがフリーズします。
std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::cout << f.get() << "\n"; // oops!
task(2,3);
TL;DR
std::asyncいくつかのことを完了させたいが、いつ完了したかをあまり気にしないstd::packaged_task場合、およびそれらを他のスレッドに移動したり後で呼び出したりするためにまとめたい場合に使用します。または、クリスチャンを引用するには:
  結局のところ、 astd::packaged_taskは実装するための低レベルの機能にすぎません (これが、 のような他の低レベルのものと一緒に使用した場合std::asyncよりも多くのことができる理由です)。簡単に言うと、 aは a にリンクされ、 aをラップして呼び出します(おそらく別のスレッドで)。std::asyncstd::threadstd::packaged_taskstd::functionstd::futurestd::asyncstd::packaged_task