std:: allocate_shared, std:: allocate_shared_for_overwrite
|
ヘッダーで定義
<memory>
|
||
|
template
<
class
T,
class
Alloc,
class
...
Args
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, Args && ... args ) ; |
(1) | (C++11以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ; |
(2) | (C++20以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ; |
(3) | (C++20以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
std::
size_t
N,
|
(4) | (C++20以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared
(
const
Alloc
&
alloc,
|
(5) | (C++20以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ; |
(6) | (C++20以降) |
|
template
<
class
T,
class
Alloc
>
shared_ptr
<
T
>
allocate_shared_for_overwrite
(
const
Alloc
&
alloc,
|
(7) | (C++20以降) |
指定された引数でオブジェクトを初期化し、
alloc
(未規定の
value_type
に対してリバインドされたもの)のコピーを使用してメモリを割り当てます。新しく作成されたオブジェクトを管理する
std::shared_ptr
オブジェクトを返します。
T
であり、
std::
allocator_traits
<
Alloc
>
::
construct
( a, pt, ( std:: forward < Args > ( args ) ... ) によって構築される。ここで pt は型 std:: remove_cv_t < T > * のポインタであり、型 std:: remove_cv_t < T > のオブジェクトを保持するのに適したストレージを指す。オブジェクトが破棄される場合、 std:: allocator_traits < Alloc > :: destroy ( a, pt ) によって破棄される。ここで pt は型 std:: remove_cv_t < T > のそのオブジェクトへのポインタである。
Alloc
であり、
alloc
の潜在的にリバウンドされたコピーです。
|
このオーバーロードは、
|
(C++20以降) |
T
が非制限配列型である場合にのみ、オーバーロード解決に参加します。
T
です。各要素はデフォルト初期値を持ちます。
T
が有界配列型である場合にのみ、オーバーロード解決に参加します。
T
が非制限配列型である場合にのみ、オーバーロード解決に参加します。
T
です。各要素の初期値は
u
です。
T
が有界配列型である場合にのみ、オーバーロード解決に参加します。
T
である。
-
Tが配列型でない場合、オブジェクトは :: new ( pv ) T によって構築される。ここで pv は型Tのオブジェクトを保持するのに適したストレージを指す void * ポインタである。オブジェクトが破棄される場合、 pt - > ~T ( ) によって破棄される。ここで pt は型Tのそのオブジェクトを指すポインタである。 -
Tが有界配列型の場合、各要素の初期値は未規定である。
T
が配列型でない場合、または有界配列型である場合にのみ、オーバーロード解決に参加します。
T
が非制限配列型である場合にのみ、オーバーロード解決に参加します。
配列要素の初期化と破棄
以下の説明において、
a
は型
型
2,3)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu
)
4,5)
std::
allocator_traits
<
Alloc
>
::
construct
(
a, pu, u
)
6,7)
::
new
(
pv
)
U
返される std::shared_ptr によって管理されるオブジェクトの寿命が終了したとき、または配列要素の初期化が例外をスローしたとき、初期化された要素は元の構築順序の逆順で破棄される。
破棄される非配列型
6,7)
pu
-
>
~U
(
)
。ここで
pu
は型
U
のその配列要素へのポインタである。
|
(C++20以降) |
パラメータ
| alloc | - | 使用する Allocator |
| args... | - |
T
のインスタンスを構築するための引数リスト
|
| N | - | 使用する配列サイズ |
| u | - | 配列の各要素を初期化するための初期値 |
戻り値
std::shared_ptr
型
T
のオブジェクトへの
または、もし
T
が非制限配列型の場合
std::
remove_extent_t
<
T
>
[
N
]
(C++20以降)
。
返される std::shared_ptr r について、 r. get ( ) は非nullポインタを返し、 r. use_count ( ) は 1 を返す。
例外
Alloc
::
allocate
(
)
または
T
のコンストラクタから送出される例外を送出する可能性があります。例外が送出された場合、
(1)
は効果を持ちません。
配列の構築中に例外が送出された場合、初期化済みの要素は逆順で破棄されます
(C++20以降)
。
注記
これらの関数は通常、参照カウントなどの内部管理構造を可能にするために、 sizeof ( T ) 以上のメモリを割り当てます。
std::make_shared
と同様に、この関数は通常1回のメモリ割り当てのみを行い、
T
オブジェクトと制御ブロックの両方を割り当てられたメモリブロックに配置します(標準ではこれを推奨していますが必須ではなく、既知の実装はすべてこれを行います)。
alloc
のコピーは制御ブロックの一部として保存され、shared参照カウントとweak参照カウントの両方がゼロに達したときに割り当て解除するために使用されます。
std::shared_ptr
の
コンストラクタ
とは異なり、
std::allocate_shared
は個別のカスタムデリーターを受け付けません:提供されたアロケータは、制御ブロックと
T
オブジェクトの破棄、およびそれらの共有メモリブロックの解放に使用されます。
|
std::shared_ptr
は配列型をサポートします(C++17以降)が、
|
(C++20まで) |
コンストラクタは
shared_from_this
を有効にし
、型
U*
のポインタ
ptr
を用いて、
U
が
明確かつアクセス可能な
(C++17以降)
std::enable_shared_from_this
の特殊化である基底クラスを持つかどうかを判定し、もしそうであれば、コンストラクタは
if
(
ptr
!
=
nullptr
&&
ptr
-
>
weak_this
.
expired
(
)
)
ptr
-
>
weak_this
=
std::
shared_ptr
<
std::
remove_cv_t
<
U
>>
(
*
this,
const_cast
<
std::
remove_cv_t
<
U
>
*
>
(
ptr
)
)
;
を評価します。
weak_this
への代入はアトミックではなく、同じオブジェクトへの潜在的な並行アクセスと競合します。これにより、将来の
shared_from_this()
の呼び出しが、この生ポインタコンストラクタによって作成された
std::shared_ptr
と所有権を共有することが保証されます。
上記のコードにおけるテスト
ptr
-
>
weak_this
.
expired
(
)
は、
weak_this
が既に所有者を示している場合に再割り当てされないことを保証します。このテストはC++17以降で必須要件となります。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_smart_ptr_for_overwrite
|
202002L
|
(C++20) |
デフォルト初期化によるスマートポインタの作成 (
std::allocate_shared_for_overwrite
,
std::make_shared_for_overwrite
,
std::make_unique_for_overwrite
); オーバーロード
(
6,7
)
|
例
#include <cstddef> #include <iostream> #include <memory> #include <memory_resource> #include <vector> class Value { int i; public: Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; } ~Value() { std::cout << "~Value(), i = " << i << '\n'; } void print() const { std::cout << "i = " << i << '\n'; } }; int main() { // 単調バッファリソースを使用してポリモーフィックアロケータを作成 std::byte buffer[sizeof(Value) * 8]; std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer)); std::pmr::polymorphic_allocator<Value> allocator(&resource); std::vector<std::shared_ptr<Value>> v; for (int i{}; i != 4; ++i) // カスタムアロケータを使用してstd::allocate_sharedを利用 v.emplace_back(std::allocate_shared<Value>(allocator, i)); for (const auto& sp : v) sp->print(); } //< すべてのshared_ptrはスコープ外に出ると自動的にクリーンアップされます。
出力:
Value(), i = 0 Value(), i = 1 Value(), i = 2 Value(), i = 3 i = 0 i = 1 i = 2 i = 3 ~Value(), i = 0 ~Value(), i = 1 ~Value(), i = 2 ~Value(), i = 3
欠陥報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| LWG 3216 | C++20 |
std::allocate_shared
は常にアロケータをリバウンドしてから
オブジェクトの構築と破棄を行っていた |
リバウンドはオプション |
| LWG 4024 | C++20 |
std::allocate_shared_for_overwrite
で構築された
オブジェクトの破棄方法が不明確だった |
明確化された |
関連項目
新しい
shared_ptr
を構築する
(公開メンバ関数) |
|
|
新しいオブジェクトを管理する共有ポインタを作成する
(関数テンプレート) |