新規なし:ポインターはC ++から削除されます

2週間前、ISO C ++標準の委員会がジャクソンビルで会合しました。 今日は短い要約を紹介し、ジャクソンビル会議でなされた革命的な決定について書きたいと思います。 詳細については、ポインターのないC ++の記事読むことをお勧めします 。 言語標準化委員会は、ポインターがC ++ 20で非推奨になり、C ++ 23から削除される可能性が最も高いと判断しました。







率直に言って、革命的と思われるのは、長い進化の最終段階に過ぎません。







画像

C ++でのポインターの進化



ポインターは最初からC ++に存在します。 Cから取得しました。C++の開発の最初から、大きな損失を伴わずにポインター管理をより安全にする傾向が常にありました。







C ++ 98では、排他的所有権を表すためにstd::auto_ptr



を取得しました。 しかし、 std::auto_ptr



は大きな欠陥がありました。 std::auto_ptr



をコピーすると、リソースの所有権がコピーに転送されます。 コピーは動くように見えました。 以下の画像は、 std::auto_ptr



不快な動作を示しています。

画像







それは非常に悪く、多くの深刻なバグにつながりました。 そのため、C ++ 11でstd::unique_ptr



を取得し、C ++ 11で非推奨のstd::auto_ptr



を宣言し、C ++ 17から完全に削除しました。 さらに、所有権を制御するために、C ++ 11でstd::shared_ptr



およびstd::weak_ptr



を取得しました。 コピーすることはできませんが、 std::unique_ptr



移動できます。また、 std::shared_ptr



をコピーまたは割り当てると、参照ポインターカウントが増加します。 ここを見てください:

画像







C ++ 11以降、C ++にはマルチスレッドライブラリがあります。 定義によりstd::shared_ptr



共有されていますが、スレッドセーフではないため、これによりstd::shared_ptr



管理が非常に複雑になります。 カウンタを備えた制御部分のみがスレッドセーフですが、監視対象リソースのアドレスにはアクセスできません。 これは、カウンターの変更がアトミック操作であることを意味しますが、リソースが一度だけ削除されるという保証はありません。 このため、C ++ 20のアトミックスマートポインターを取得します: std::atomic_shared_ptr



およびstd::atmic_weak_ptr



標準化委員会の提案の詳細については、「 Atomic smart pointers」を参照してください。







次に、将来のC ++ 20およびC ++ 23標準のより興味深い部分に移りましょう。 ポインターはC ++ 20で非推奨になり、C ++ 23から削除されます。 次の3つの単語を考えてみましょう。NoNew New(NNN)。







std :: unique_ptrは私たちを救います



しかし、待ってください。C++の教義はどうですか。不要なものにお金を払わないでください。 ポインターなしでどのようにプログラムできますか? std::unique_ptr



使用してください。 その設計から、 std::unique_ptr



は、通常のポインターと同じくらい高速で経済的であり、自動リソース管理という明確な利点があります。







以下は、簡単なパフォーマンステストです。







 // all.cpp #include <chrono> #include <iostream> static const long long numInt= 100000000; int main(){ auto start = std::chrono::system_clock::now(); for ( long long i=0 ; i < numInt; ++i){ int* tmp(new int(i)); delete tmp; // std::shared_ptr<int> tmp(new int(i)); // std::shared_ptr<int> tmp(std::make_shared<int>(i)); // std::unique_ptr<int> tmp(new int(i)); // std::unique_ptr<int> tmp(std::make_unique<int>(i)); } std::chrono::duration<double> dur= std::chrono::system_clock::now() - start; std::cout << "time native: " << dur.count() << " seconds" << std::endl; }
      
      





このプログラムは、1億int



メモリを割り当てて解放しint



。 ポインターstd::shared_ptr



およびstd::unique_ptr



を2つのバリエーションで使用します。 LinuxおよびWindowsで最大限の最適化の有無にかかわらずプログラムをコンパイルしています。 次の数値が取得されます。

画像







LinuxおよびWindowsのstd::unique_ptr



2つのバリエーションは、通常のポインターと同じパフォーマンスを示します。 このテストの詳細については、前回の記事「 メモリ消費とスマートポインタパフォーマンス」を参照してください。







所有権のセマンティクス



正直なところ、私たちはポインターを使用しています。特に、通常のポインターを頻繁に使用しています。 ポインターを使用する必要があるかどうかの問題は、次のようになります。所有者は誰ですか? 幸いなことに、コードの助けを借りて、これを明確に表現できます。









ポインターを使用するための6つのプラクティスのうちの1つを変更するだけで済み、C ++の開発における次のステップに満足しています。








All Articles