C++11学習メモ(3) - 一般ツール(オン) (重要な機能を含む スマートポインタ スマートポインタ)

1ペア

C++11 では、std::pair は 2 つの値を 1 つの単位に結合するために使用されるテンプレート クラスです。異なるタイプの 2 つの値をペアにすることができ、値のペアへのアクセスと操作を提供します。

std::pair の定義

template<class T1, class T2>
struct pair{
    
    
	T1 first;
	T2 second;
};

いくつかの使用法

作成して初期化します。

std::pair オブジェクトは、コンストラクターまたは中括弧付き初期化子リストを使用して作成および初期化できます。例えば:

std::pair<int, std::string> myPair(42, "Hello");
std::pair<double, bool> anotherPair = {
    
    3.14, true};

訪問会員

std::pair オブジェクトのメンバーには、.first および .second を通じてアクセスできます。例えば:

std::pair<int, std::string> myPair(42, "Hello");
int x = myPair.first;
std::string str = myPair.second;

比較して並べ替える

std::pair は比較演算を実行でき、.first と .second の値に従って比較します。std::pair オブジェクトはコンテナ内で並べ替えることができます。例えば:

std::pair<int, std::string> pair1(42, "Hello");
std::pair<int, std::string> pair2(10, "World");

bool result = (pair1 < pair2);  // 比较操作
std::vector<std::pair<int, std::string>> myVector = {
    
    pair1, pair2};
std::sort(myVector.begin(), myVector.end());  // 容器排序

使用例:

std::pair は、複数の値を返す関数や、2 つの値を 1 つの単位として渡す必要がある状況でよく使用されます。例えば:

std::pair<int, std::string> getPerson() {
    
    
    int age = 25;
    std::string name = "John";
    return std::make_pair(age, name);
}

std::pair<int, int> divideAndRemainder(int dividend, int divisor) {
    
    
    int quotient = dividend / divisor;
    int remainder = dividend % divisor;
    return {
    
    quotient, remainder};
}

make_pair()

ペア オブジェクトは、タイプを書き出さずに生成できます。次に例を示します。

std::pair<int, char> myPair(42, "Hello");
std::make_pair(42, "Hello");

操作機能

ここに画像の説明を挿入

std::pair は 2 つの値を組み合わせる便利な方法を提供し、さまざまなシナリオで使用できます。これは、コードを簡素化し、コードの読みやすさを向上させるために C++ で一般的に使用されるツールの 1 つです。

2.タプル

タプルは、ペアの概念を拡張して、任意の数の要素を持ち、それぞれの型を指定できます。

タプルの定義

template<typename... Types>
class tuple;

タプルの例

#include <iostream>
#include <tuple>

int main() {
    
    
    // 创建一个包含整数、字符串和浮点数的元组
    std::tuple<int, std::string, double> myTuple(42, "Hello", 3.14);

    // 访问元组中的元素
    int intValue = std::get<0>(myTuple);
    std::string stringValue = std::get<1>(myTuple);
    double doubleValue = std::get<2>(myTuple);

    // 修改元组中的元素
    std::get<0>(myTuple) = 100;

    // 使用tie函数将元组的元素解包到变量中
    
    int a;
    std::string b;
    double c;
    std::tie(a, b, c) = myTuple;
		//std::tie(a, std::ignore, c) = myTuple;忽略某些元素
    // 打印元组的元素
    std::cout << "Tuple elements: " << a << ", " << b << ", " << c << std::endl;
		//c++11也可直接输出myTuple
    return 0;
}

操作機能

ここに画像の説明を挿入

std::tuple_size

std::tuple のサイズを取得するために使用されます。

#include <iostream>
#include <tuple>

int main() {
    
    
    std::tuple<int, std::string, double> myTuple;

    std::cout << "Tuple size: " << std::tuple_size<decltype(myTuple)>::value << std::endl;

    return 0;
}

出力結果は「タプル サイズ: 3」となり、std::tuple に 3 つの要素があることを示します。

std::tuple_element

std::tuple 内の指定された位置にある要素の型を取得するために使用されます。


#include <iostream>
#include <tuple>

int main() {
    
    
    using MyTuple = std::tuple<int, std::string, double>;

    std::tuple_element<1, MyTuple>::type myElement;

    std::cout << "Element type: " << typeid(myElement).name() << std::endl;

    return 0;
}

出力結果は次のようになります。要素タイプ: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE は、std::tuple の 2 番目の要素タイプが std::string であることを示します。

std::tuple_cat

複数の std::tuple を 1 つの大きな std::tuple に結合するために使用されます。


#include <iostream>
#include <tuple>

int main() {
    
    
    std::tuple<int, std::string> tuple1(42, "Hello");
    std::tuple<double> tuple2(3.14);

    auto combinedTuple = std::tuple_cat(tuple1, tuple2);

    std::cout << "Combined tuple size: " << std::tuple_size<decltype(combinedTuple)>::value << std::endl;

    return 0;
}

出力結果は次のようになります。結合タプル サイズ: 3。これは、tuple1 と tuple2 を結合した後、3 つの要素を含む std::tuple が取得されることを意味します。

ペアとタプル

std::pair から std::tuple への変換

std::pair は、std::make_tuple 関数を使用して std::tuple に変換できます。

#include <iostream>
#include <tuple>

int main() {
    
    
    std::pair<int, double> myPair(42, 3.14);

    std::tuple<int, double> myTuple = std::make_tuple(myPair.first, myPair.second);

    std::cout << "Tuple elements: " << std::get<0>(myTuple) << ", " << std::get<1>(myTuple) << std::endl;

    return 0;
}

上の例では、 std::pair<int, double> 型のオブジェクト myPair があり、 std::make_tuple を使用して、それを std::tuple<int, double> 型のオブジェクト myTuple に変換できます。

std::tuple から std::pair への変換

std::get 関数を使用して std::tuple の要素を抽出し、これらの要素を使用して std::pair を作成できます。


#include <iostream>
#include <tuple>

int main() {
    
    
    std::tuple<int, double> myTuple(42, 3.14);

    std::pair<int, double> myPair = std::make_pair(std::get<0>(myTuple), std::get<1>(myTuple));

    std::cout << "Pair elements: " << myPair.first << ", " << myPair.second << std::endl;

    return 0;
}

上記の例では、タイプ std::tuple<int, double> のオブジェクト myTuple があり、 std::get 関数を使用してその要素を抽出し、これらの要素を使用してタイプ std::pair<int, double> のオブジェクト myPair を作成できます。

3.スマートポインター***

ポインタは C/C++ の重要な機能ですが、使用中にダングリング、複数の削除、リソース リークなどの問題が頻繁に発生します。これらの問題を回避する一般的な方法は、スマート ポインタを使用することです。
C++11 以降、標準ライブラリは、shared_ptr と unique_ptr の 2 種類のスマート ポインターを提供します。auto_ptr は非推奨ですが、これらは <memory> で定義されています。

共有_ptr

std::shared_ptr は、スマート ポインターの一種として、動的に割り当てられたメモリをより安全かつ便利に管理するために使用されます。std::shared_ptr は、参照カウントを使用してリソースの所有者を追跡し、リソースが不要になったときに自動的に解放します。

以下は、std::shared_ptr の基本的な使用法と例です。

std::shared_ptr オブジェクトを作成します。

std::shared_ptr オブジェクトは、 std::make_shared 関数を使用するか、 std::shared_ptr コンストラクターを直接使用して作成できます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
    std::shared_ptr<int> ptr2(new int(100));

    std::cout << *ptr1 << std::endl; // 输出:42
    std::cout << *ptr2 << std::endl; // 输出:100

    return 0;
}

上記の例では、std::make_shared を使用して整数値を含む std::shared_ptr オブジェクト ptr1 を作成し、std::shared_ptr のコンストラクターを使用して別の std::shared_ptr オブジェクト ptr2 を作成します。

共有所有リソース:

1 つの std::shared_ptr を別の std::shared_ptr に割り当てて、同じリソースの所有権を共有することができます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
    std::shared_ptr<int> ptr2 = ptr1;

    std::cout << *ptr1 << std::endl; // 输出:42
    std::cout << *ptr2 << std::endl; // 输出:42

    return 0;
}

上の例では、ptr1 を ptr2 に割り当てました。これらは両方とも同じ整数リソースを指し、そのリソースの所有権を共有します。

参照カウントとリソース解放:

std::shared_ptr は、参照カウントを使用してリソースの所有者の数を追跡します。最後の std::shared_ptr が破棄されるか、新しい値が割り当てられると、参照カウントがデクリメントされ、リソースを解放する必要があるかどうかがチェックされます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
    std::shared_ptr<int> ptr2 = ptr1;
    std::shared_ptr<int> ptr3 = ptr1;

    std::cout << *ptr1 << std::endl; // 输出:42
    std::cout << *ptr2 << std::endl; // 输出:42
    std::cout << *ptr3 << std::endl; // 输出:42

    ptr1.reset();

    std::cout << std::boolalpha;
    std::cout << "ptr1 is nullptr: " << (ptr1 == nullptr) << std::endl; // 输出:true
    std::cout << "ptr2 is nullptr: " << (ptr2 == nullptr) << std::endl; // 输出:false
    std::cout << "ptr3 is nullptr: " << (ptr3 == nullptr) << std::endl; // 输出:false

    return 0;
}

上記の例では、3 つの std::shared_ptr オブジェクト ptr1、ptr2、ptr3 を作成しました。これらはすべて同じ整数リソースを指します。ptr1 がリセット関数を呼び出すと、ptr1 はリソースを所有しなくなり、参照カウントが減少してリソースが解放されますが、ptr2 と ptr3 は引き続き有効であり、リソースを所有します。

std::shared_ptr は、get (基礎となるポインターを返す)、use_count (参照カウントを返す)、unique (唯一の所有者であるかどうかを確認する) など、他の便利なメンバー関数も提供します。

std::shared_ptr を使用すると、メモリ リークやダングリング ポインタなどの問題を効果的に回避し、便利なリソース管理メカニズムを提供できます。ただし、循環参照の問題が発生するとリソースが解放されなくなる可能性があるため、循環参照の問題を避けるように注意してください。

デストラクター

std::shared_ptr のデストラクターは、テンプレート パラメーターで指定されたデリーターによって実行されます。カスタム削除機能を提供することで、破棄動作をカスタマイズできます。

デリーターは、std::shared_ptr の参照カウントがゼロに達したときにリソースの割り当て解除を実行する呼び出し可能なオブジェクトです。デリーターには、関数ポインター、関数オブジェクト、ラムダ式、またはカスタム タイプのオブジェクトを指定できます。

カスタム デリーターを使用した例を次に示します。

#include <iostream>
#include <memory>

// 自定义删除器
struct CustomDeleter {
    
    
    void operator()(int* ptr) {
    
    
        std::cout << "Custom deleter is called" << std::endl;
        delete ptr;
    }
};

int main() {
    
    
    std::shared_ptr<int> ptr(new int(42), CustomDeleter());

    return 0;
}

上の例では、CustomDeleter という構造体を定義します。これは、括弧演算子をオーバーロードしてカスタムの削除動作を実装します。main 関数では、std::shared_ptr のコンストラクターを使用して std::shared_ptr オブジェクト ptr を作成し、カスタム デリーターをパラメーターとして渡します。

std::shared_ptr の参照カウントがゼロになると、カスタム デリーターのかっこ演算子が呼び出され、リソースが解放され、定義したカスタム削除動作が実行されます。この例では、カスタム デリーターはメッセージを出力し、整数へのポインターを削除します。

カスタム デリーターを提供する場合は、デリーターがポインター タイプと互換性があり、適切なリソース リリース ルールに従っていることを確認する必要があることに注意してください。デリーターをカスタマイズすることで、特定のニーズに合わせて、より柔軟なリソース管理と破棄動作を実現できます。

その他の操作

ここに画像の説明を挿入ここに画像の説明を挿入

弱い_ptr

C++11 では、std::shared_ptr が引き起こす可能性のある循環参照の問題を解決するために、スマート ポインター型として std::weak_ptr が導入されています。std::weak_ptr を使用すると、参照カウントを増やしたり、オブジェクトの破棄を防ぐことなく、std::shared_ptr によって管理されるオブジェクトへの弱い参照が可能になります。

以下は、std::weak_ptr の基本的な使用法と例です。

std::weak_ptr オブジェクトを作成する

std::weak_ptr オブジェクトは、std::shared_ptr オブジェクトを std::weak_ptr にキャストすることで作成できます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
    std::weak_ptr<int> weakPtr = sharedPtr;

    // 输出:42
    if (auto lockedPtr = weakPtr.lock()) {
    
    
        std::cout << *lockedPtr << std::endl;
    } else {
    
    
        std::cout << "Resource has been released" << std::endl;
    }

    return 0;
}

上記の例では、整数リソースを管理するために std::shared_ptr オブジェクトsharedPtrを作成し、それをstd::weak_ptrに変換してstd::weak_ptrオブジェクトweakPtrを作成しました。std::weak_ptr にキャストしてもリソースの参照数は増加しないことに注意してください。

std::weak_ptr が有効かどうかを確認し、リソースにアクセスします

lock() 関数を使用すると、std::weak_ptr が有効かどうかを確認し、リソースへの共有アクセスを取得できます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::weak_ptr<int> weakPtr;

    {
    
    
        std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
        weakPtr = sharedPtr;

        // 输出:42
        if (auto lockedPtr = weakPtr.lock()) {
    
    
            std::cout << *lockedPtr << std::endl;
        } else {
    
    
            std::cout << "Resource has been released" << std::endl;
        }
    }

    // 输出:"Resource has been released"
    if (auto lockedPtr = weakPtr.lock()) {
    
    
        std::cout << *lockedPtr << std::endl;
    } else {
    
    
        std::cout << "Resource has been released" << std::endl;
    }

    return 0;
}

上記の例では、スコープ内に std::shared_ptr オブジェクトsharedPtrを作成し、それをstd::weak_ptrオブジェクトweakPtrに変換しました。スコープが終了すると、sharedPtr が破棄され、リソースが解放されます。後続のコードでは、weakPtr が有効かどうかを確認し、lock() 関数を呼び出してリソースにアクセスします。weakPtr が有効な場合、lock() 関数は有効な std::shared_ptr オブジェクトを返します。それ以外の場合は、null ポインタを返します。

リソースを見る

期限切れ()

std::weak_ptr の有効期限が切れているかどうか (つまり、指定されたリソースが解放されているかどうか) を確認するために使用されます。リソースが解放されている場合は true を返し、それ以外の場合は false を返します。

use_count()

std::weak_ptr と同じリソースを取得するために使用される有効な std::shared_ptr オブジェクトの数。

#include <iostream>
#include <memory>

int main() {
    
    
    std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
    std::weak_ptr<int> weakPtr = sharedPtr;

    // 输出:1
    std::cout << "use_count: " << sharedPtr.use_count() << std::endl;

    if (weakPtr.expired()) {
    
    
        std::cout << "Resource has been released" << std::endl;
    } else {
    
    
        // 输出:42
        std::cout << "Value: " << *weakPtr.lock() << std::endl;
    }

    sharedPtr.reset();

    // 输出:0
    std::cout << "use_count: " << weakPtr.use_count() << std::endl;

    if (weakPtr.expired()) {
    
    
        std::cout << "Resource has been released" << std::endl;
    } else {
    
    
        std::cout << "Value: " << *weakPtr.lock() << std::endl;
    }

    return 0;
}

上記の例では、整数リソースを管理するために std::shared_ptr オブジェクトsharedPtrを作成し、それをstd::weak_ptrオブジェクトweakPtrに変換することで弱参照を作成しました。use_count() 関数を使用して、sharedPtr と同じリソースを共有する有効な std::shared_ptr オブジェクトの数を取得します。if ステートメントでは、expired() 関数を使用してweakPtr の有効期限が切れているかどうかを確認し、lock() 関数を使用して有効な std::shared_ptr オブジェクトを取得し、その値を出力します。後続のコードでは、reset() 関数を呼び出して、sharedPtr を空にし、リソースを解放し、weakPtr の有効期限が切れているかどうかを確認します。

std::weak_ptr は参照カウントを増加させないため、 use_count() 関数を呼び出すと、リソースを共有する有効な std::shared_ptr オブジェクトの数が返されることに注意してください。

その他の操作

ここに画像の説明を挿入

std::weak_ptr を使用することで、std::shared_ptr が引き起こす循環参照の問題を回避し、リソースのライフサイクルをより柔軟に管理できます。

unique_ptr

std::unique_ptr は排他的所有権を持つスマート ポインターです。つまり、ポインターが指すオブジェクトを所有できるのは一度に 1 つの std::unique_ptr だけです。unique_ptr が破棄されると、それが指すオブジェクトは自動的に破棄されます。

以下は、std::unique_ptr の基本的な使用法と例です。

std::unique_ptr オブジェクトを作成する

std::unique_ptr オブジェクトは、 std::make_unique 関数を使用するか、 std::unique_ptr コンストラクターを直接使用して作成できます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::unique_ptr<int> uniquePtr1 = std::make_unique<int>(42);
    std::unique_ptr<int> uniquePtr2(new int(100));

    // 输出:42
    std::cout << *uniquePtr1 << std::endl;

    // 输出:100
    std::cout << *uniquePtr2 << std::endl;

    return 0;
}

上記の例では、 std::make_unique 関数とコンストラクターを使用して 2 つの std::unique_ptr オブジェクト uniquePtr1 と uniquePtr2 を作成し、2 つの整数リソースを管理します。なお、std::make_unique は C++14 で導入された関数ですが、C++11 を使用している場合は std::unique_ptr のコンストラクタを直接使用できます。

所有権移転を実行する

std::unique_ptr には排他的所有権の機能があり、移動セマンティクスを通じて所有権を 1 つの std::unique_ptr から別の std::unique_ptr に転送できます。

#include <iostream>
#include <memory>

int main() {
    
    
    std::unique_ptr<int> uniquePtr1 = std::make_unique<int>(42);
    std::unique_ptr<int> uniquePtr2;

    uniquePtr2 = std::move(uniquePtr1);

    // 输出:42
    std::cout << *uniquePtr2 << std::endl;

    return 0;
}

上記の例では、std::move を使用して uniquePtr1 の所有権を uniquePtr2 に転送しました。このようにして、 uniquePtr2 が元のリソースを所有するようになり、 uniquePtr1 はリソースを所有しなくなります。

カスタム削除器を使用する

可以通过提供自定义删除器来指定std::unique_ptr在释放资源时的行为。删除器是一个函数对象或函数指针,用于定义资源释放的方式。
#include <iostream>
#include <memory>

struct CustomDeleter {
    
    
    void operator()(int* ptr) {
    
    
        std::cout << "Deleting resource: " << *ptr << std::endl;
        delete ptr;
    }
};

int main() {
    
    
    std::unique_ptr<int, CustomDeleter> uniquePtr(new int(42));

    // 输出:42
    std::cout << *uniquePtr << std::endl;

    return 0;
}

上記の例では、カスタム デリーター CustomDeleter を使用して std::unique_ptr オブジェクト uniquePtr を作成しました。uniquePtr が破棄されると、カスタム デリーターが呼び出され、リソースを解放します。

std::unique_ptr は、単一の所有権でオブジェクトを管理するのに適した軽量のスマート ポインタを提供し、効率的なメモリ管理と安全なリソース解放を提供します。

配列について

C++ では、配列を削除するには delete[] を使用する必要があります。C++ ではポインタが単一のオブジェクトを指しているのか配列を指しているのかを区別できないため、ポインタが自動的に削除されるとエラーが発生します。標準ライブラリでは、このための特別なバージョンが提供されています。
C++11 では、std::unique_ptr の配列バージョン、つまり std::unique_ptr<T[]> が導入され、動的に割り当てられた配列オブジェクトを管理するために使用されます。

以下は、動的配列を管理する std::unique_ptr の例です。

#include <iostream>
#include <memory>

int main() {
    
    
    std::unique_ptr<int[]> uniquePtr(new int[5]);

    for (int i = 0; i < 5; i++) {
    
    
        uniquePtr[i] = i + 1;
    }

    for (int i = 0; i < 5; i++) {
    
    
        std::cout << uniquePtr[i] << " ";
    }

    // 输出:1 2 3 4 5
    std::cout << std::endl;

    return 0;
}

上記の例では、 std::unique_ptr<int[]> を使用して std::unique_ptr オブジェクト uniquePtr を作成し、5 つの整数を含む動的配列を管理します。配列添字演算子 [] を使用すると、配列内の要素にアクセスして変更できます。uniquePtr が破棄されると、動的配列によって占有されていたメモリが自動的に解放されます。

std::unique_ptr<T[]> は、既存の配列を指すのではなく、新しい T[] によって動的に割り当てられた配列の管理にのみ適していることに注意してください。このバージョンでは、演算子 '*' および '->' が提供されません。std::unique_ptr<T[]> を使用する場合、メモリを解放するために delete[] を手動で呼び出す必要はありません。std::unique_ptr が自動的にメモリの解放を処理します。さらに、このバージョンでは、異なる型間の直接変換はサポートされておらず、派生要素型へのポインターは許可されていません。

その他の操作

ここに画像の説明を挿入

auto_ptr

std::auto_ptr は、動的に割り当てられたオブジェクトを管理するために C++98 標準によって導入されたスマート ポインターです。ただし、std::auto_ptr は C++11 以降非推奨になっており、いくつかのバグや安全でない動作のため、新しいコードには推奨されません。
std::auto_ptr に関する重要な注意事項をいくつか示します。

所有権の移転

std::unique_ptr とは異なり、std::auto_ptr は所有権の譲渡をサポートしています。つまり、リソースの所有権をある std::auto_ptr から別の std::auto_ptr に譲渡できます。これは、所有権を譲渡した後、元の std::auto_ptr がリソースを所有しなくなることを意味します。

配列はサポートされていません

std::auto_ptr は単一オブジェクトの管理にのみ適しており、動的に割り当てられた配列の管理はサポートしていません。

デリーターの制限事項

std::auto_ptr はデフォルトのデリーターの使用のみをサポートし、デリーターをカスタマイズすることはできません。つまり、 std::auto_ptr が破棄されると、リソースを解放するために delete のみが呼び出されます。

安全でないコピーのセマンティクス

std::auto_ptr のコピー セマンティクスには問題があり、従来のコピー セマンティクスの代わりに移動セマンティクスが使用されます。これにより、コピー後に元の std::auto_ptr がリソースの所有権を失い、リソースが繰り返し解放される可能性があります。

したがって、排他的所有権の場合には std::unique_ptr、共有所有権の場合には std::shared_ptr、循環参照の問題を解決するには std::weak_ptr など、C++11 で導入されたより安全で強力なスマート ポインター型を使用することをお勧めします。これらのスマート ポインター タイプは、より優れたセマンティクスとより強力な型チェックを提供し、より適切なリソース管理を可能にし、より優れたメモリの安全性を提供します。

補充する

メモリのオーバーヘッド

生のポインタと比較すると、スマート ポインタは通常、特定のメモリ オーバーヘッドを導入します。スマート ポインター オブジェクトには通常、参照カウントなどの追加のデータ メンバーが含まれており、より多くのメモリを使用する可能性があります。ほとんどの場合、このオーバーヘッドは無視できますが、リソースが非常に限られている組み込みシステムなどの特殊な環境では、スマート ポインターの使用を慎重に検討する必要があります。

状況によっては適さない

スマート ポインターは、あらゆる状況に対応できる一般的なソリューションではありません。C インターフェイスとの対話、外部リソースの処理など、一部の特定のアプリケーション シナリオでは、リソースを手動で管理する必要がある場合があり、スマート ポインターの使用には適していません。

意味上の違いと注意点

スマート ポインターの種類が異なればセマンティクスや動作も異なるため、その使用方法についての理解と注意が必要です。たとえば、std::shared_ptr の共有所有権は追加のオーバーヘッドとスレッド セーフティの問題を引き起こす可能性がありますが、std::unique_ptr は排他的所有権のシナリオに適しています。さらに、スマート ポインターの使用では、循環参照、null ポインター チェック、潜在的なパフォーマンスへの影響などの問題にも注意する必要があります。

スマート ポインターには欠点や注意点もありますが、ほとんどの場合、リソースを管理する便利で安全、信頼できる方法を提供します。スマート ポインターを使用する場合は、そのセマンティクスと動作を理解し、特定のアプリケーション シナリオと組み合わせて選択して使用する必要があります。

おすすめ

転載: blog.csdn.net/qq_44616044/article/details/131184594