新規なし:ポインターは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 ++の開発における次のステップに満足しています。



Source: https://habr.com/ru/post/J352570/


All Articles