に関するちょっとした質問shared_ptr
です。
shared_ptr
配列を指すことを使用することは良い習慣ですか? 例えば、
shared_ptr<int> sp(new int[10]);
そうでない場合、なぜですか?私がすでに認識している理由の 1 つは、 をインクリメント/デクリメントできないことshared_ptr
です。したがって、配列への通常のポインターのようには使用できません。
に関するちょっとした質問shared_ptr
です。
shared_ptr
配列を指すことを使用することは良い習慣ですか? 例えば、
shared_ptr<int> sp(new int[10]);
そうでない場合、なぜですか?私がすでに認識している理由の 1 つは、 をインクリメント/デクリメントできないことshared_ptr
です。したがって、配列への通常のポインターのようには使用できません。
C++17では、shared_ptr
動的に割り当てられた配列を管理するために使用できます。この場合のshared_ptr
テンプレート引数はT[N]
またはでなければなりませんT[]
。だからあなたは書くかもしれません
shared_ptr<int[]> sp(new int[10]);
n4659より、[util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requires:
Y
完全な型でなければなりません。式が配列型のdelete[] p
場合T
、または が配列型でないdelete p
場合、T
式は明確に定義された動作をし、例外をスローしません。
...
備考:T
が配列型の場合、このコンストラクターは、式が整形式であり、 is および is に変換可能であるか、または is and is に変換可能でない限り、オーバーdelete[] p
ロードの 解決に参加T
しU[N]
ません。...Y(*)[N]
T*
T
U[]
Y(*)[]
T*
これをサポートするために、メンバー型element_type
は次のように定義されています。
using element_type = remove_extent_t<T>;
配列要素は次を使用してアクセスできますoperator[]
element_type& operator[](ptrdiff_t i) const;
必要:
get() != 0 && i >= 0
.T
の場合U[N]
、i < N
。...
備考:が配列型でない場合T
、このメンバー関数が宣言されているかどうかは不定です。関数が宣言されている場合、その戻り値の型が何であるかは指定されていませんが、関数の宣言 (必ずしも定義である必要はありません) が適切に形成されている必要があります。
C++17 より前では、動的に割り当てられた配列の管理には使用shared_ptr
できませんでした。デフォルトでは、管理対象オブジェクトへの参照がなくなると、管理対象オブジェクトshared_ptr
が呼び出されます。delete
ただし、 using を使用して割り当てる場合は、 ではなくnew[]
を呼び出して、リソースを解放する必要があります。delete[]
delete
配列で正しく使用するshared_ptr
には、カスタムのデリータを提供する必要があります。
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
次のように shared_ptr を作成します。
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
管理オブジェクトを破棄するときshared_ptr
に正しく呼び出されるようになりました。delete[]
上記のカスタム デリーターは、
配列型のstd::default_delete
部分的な特殊化
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
ラムダ式
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
また、管理対象オブジェクトの共有権限が実際に必要でない限り、unique_ptr
配列型の部分的な特殊化があるため、このタスクには a の方が適しています。
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
上記にリストされているものに代わる C++17 以前の別の代替手段がLibrary Fundamentals Technical Specificationshared_ptr
によって提供されました。これは、オブジェクトの配列を所有している場合にすぐに使用できるように拡張されています。shared_ptr
この TS に予定されている変更の現在のドラフトは、N4082にあります。これらの変更はstd::experimental
名前空間を介してアクセスでき、<experimental/memory>
ヘッダーに含まれます。shared_ptr
配列のサポートに関連するいくつかの変更は次のとおりです。
— メンバー タイプの定義がelement_type
変更されました
typedef T element_type;typedef typename remove_extent<T>::type element_type;
— メンバーoperator[]
が追加されています
element_type& operator[](ptrdiff_t i) const noexcept;
unique_ptr
—配列の部分的な特殊化とは異なり、shared_ptr<T[]>
とのshared_ptr<T[N]>
両方が有効であり、どちらもdelete[]
オブジェクトのマネージド配列で呼び出されます。
template<class Y> explicit shared_ptr(Y* p);
Requires :
Y
完全な型でなければなりません。が配列型の場合、またはが配列型でないdelete[] p
場合の式は、整形式であり、動作が明確に定義されていなければならず、例外をスローしてはなりません。の場合、に変換可能です。の場合、に変換可能です。それ以外の場合は、に変換できるものとします。T
delete p
T
T
U[N]
Y(*)[N]
T*
T
U[]
Y(*)[]
T*
Y*
T*
使用できる可能性のあるより簡単な代替手段は ですshared_ptr<vector<int>>
。