技術共有

【C】スマートポインター

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

スマートポインターの説明

スマート ポインターは、動的に割り当てられたメモリを自動的に管理するために使用される C++ のツールです。

これは、生のポインタの機能をカプセル化するクラスであり、リソースの割り当てと解放を自動的に処理できるため、プログラマがメモリ リーク、ダングリング ポインタ、その他の問題などの一般的なメモリ管理エラーを回避するのに役立ちます。

スマート ポインターは、リソース取得は初期化 (RAII) メカニズムを通じて機能します。つまり、スマート ポインターは、構築時にリソースを取得し、破棄時にリソースを解放します。これにより、異常な状況下でもリソースが正しく解放されることが保証されます。

 

スマートポインターで解決できる問題

(1) メモリリーク:メモリは手動で解放されますが、スマートポインタを使用して自動的に解放することもできます。

(2) 共有所有権ポインタの伝播と解放。複数のスレッドが同じオブジェクトを使用する場合の破壊の問題など。

 

数種類のスマート ポインター

C++ 標準ライブラリは、次のようないくつかのタイプのスマート ポインターを提供します。

  1. std::unique_ptr

    • 独占的所有権モデル、つまりunique_ptrインスタンスは、それが指すオブジェクトの排他的所有権を持ちます。
    • いつunique_ptrスコープ外になるか明示的にリセットされると、自動的にデストラクターが呼び出され、管理対象オブジェクトが解放されます。
    • コピーはサポートされていませんが、移動は可能です。
  2. std::shared_ptr

    • 共有所有権モデル、複数の所有権を許可shared_ptrインスタンスは同じオブジェクトの所有権を共有します。
    • 参照カウントを使用して同じオブジェクトへの参照を追跡するshared_ptr量。
    • 最後はいつshared_ptrインスタンスがスコープ外になるかリセットされると、参照カウントがゼロに減らされ、オブジェクトのデストラクターが呼び出され、オブジェクトが解放されます。
  3. std::weak_ptr

    • 解決するために使用されるshared_ptr循環参照の問題。
    • 参照カウントを増やさなくても、次のように監視できます。shared_ptr管理対象オブジェクトですが、そのライフサイクル管理には参加しません。
    • 無いときはshared_ptrインスタンスがオブジェクトを指すとき、weak_ptrオブジェクトが破壊されたことを検出できます。

スマート ポインターの設計と使用により、C++ でのメモリ管理が大幅に簡素化され、プログラムの堅牢性とセキュリティが向上します。最新の C++ プログラミングでは、コードの品質と保守性を向上させるために、生のポインターの代わりにスマート ポインターを使用することを強くお勧めします。

 

スマートポインターの例

スマート ポインタは、メモリ リークやその他のリソース管理関連の問題を防ぐために、動的に割り当てられたメモリを自動的に管理する手段として C++ で使用されます。

std::unique_ptr

std::unique_ptr排他的所有権を持つスマート ポインターです。これにより、確実に 1 つだけが存在します。std::unique_ptrインスタンスは特定のリソースを制御します。いつstd::unique_ptrスコープ外になるかリセットされると、所有するリソースは自動的に解放されます。

  1. #include <memory>
  2. class MyClass {
  3. public:
  4. MyClass() { std::cout << "MyClass constructor called.n"; }
  5. ~MyClass() { std::cout << "MyClass destructor called.n"; }
  6. void doSomething() { std::cout << "Doing something...n"; }
  7. };
  8. int main() {
  9. // 创建一个unique_ptr来管理MyClass的实例
  10. std::unique_ptr<MyClass> uptr(new MyClass());
  11. // 调用doSomething方法
  12. uptr->doSomething();
  13. // unique_ptr会在离开作用域时自动调用MyClass的析构函数
  14. return 0;
  15. }

std::shared_ptr

std::shared_ptrは、複数のアクセスを許可する共有所有権スマート ポインターです。std::shared_ptrインスタンスは同じリソースの所有権を共有します。std::shared_ptr参照カウントを使用して、同じリソースを指すスマート ポインターの数を追跡します。参照カウントが 0 に達すると、リソースが解放されます。

  1. #include <memory>
  2. class MyClass {
  3. public:
  4. MyClass() { std::cout << "MyClass constructor called.n"; }
  5. ~MyClass() { std::cout << "MyClass destructor called.n"; }
  6. void doSomething() { std::cout << "Doing something...n"; }
  7. };
  8. int main() {
  9. // 创建一个shared_ptr来管理MyClass的实例
  10. std::shared_ptr<MyClass> sptr(new MyClass());
  11. // 创建第二个shared_ptr,共享同一个MyClass实例
  12. std::shared_ptr<MyClass> sptr2 = sptr;
  13. // 调用doSomething方法
  14. sptr->doSomething();
  15. // 当所有shared_ptr实例都超出作用域时,MyClass的析构函数才会被调用
  16. return 0;
  17. }

 

予防

使用中でstd::shared_ptrこれを行うときは、循環参照の状況を避けるように注意してください。循環参照の状況では、参照カウントが 0 に下がらず、リソース リークが発生します。循環参照の場合は、次のように使用できます。std::weak_ptrサイクルを断ち切るために、std::weak_ptr参照カウントはインクリメントせず、保持するだけです。std::shared_ptrリソースへの弱い参照を管理します。

これらの例は、スマート ポインタを使用して動的に割り当てられたメモリを管理し、リソースが適切なタイミングで適切に解放されるようにし、メモリを手動で管理するときに発生する可能性のある一般的な間違いを回避する方法を示しています。

 

その他の例

https://www.cnblogs.com/god-of-death/p/17962676

https://zhuanlan.zhihu.com/p/678722914