Namespaces
Variants

std:: allocate_shared, std:: allocate_shared_for_overwrite

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
ヘッダーで定義 <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,

const std:: remove_extent_t < T > & u ) ;
(4) (C++20以降)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc,

const std:: remove_extent_t < T > & u ) ;
(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,

std:: size_t N ) ;
(7) (C++20以降)

指定された引数でオブジェクトを初期化し、 alloc (未規定の value_type に対してリバインドされたもの)のコピーを使用してメモリを割り当てます。新しく作成されたオブジェクトを管理する std::shared_ptr オブジェクトを返します。

1) オブジェクトは型 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 > のそのオブジェクトへのポインタである。
上記の説明において、 a は型 Alloc であり、 alloc の潜在的にリバウンドされたコピーです。

このオーバーロードは、 T が配列型でない場合にのみオーバーロード解決に参加します。

(C++20以降)
2) オブジェクトの型は std:: remove_extent_t < T > [ N ] です。各要素はデフォルト初期値を持ちます。
このオーバーロードは、 T が非制限配列型である場合にのみ、オーバーロード解決に参加します。
3) オブジェクトの型は T です。各要素はデフォルト初期値を持ちます。
このオーバーロードは、 T が有界配列型である場合にのみ、オーバーロード解決に参加します。
4) オブジェクトの型は std:: remove_extent_t < T > [ N ] です。各要素は初期値 u を持ちます。
このオーバーロードは、 T が非制限配列型である場合にのみ、オーバーロード解決に参加します。
5) オブジェクトの型は T です。各要素の初期値は u です。
このオーバーロードは、 T が有界配列型である場合にのみ、オーバーロード解決に参加します。
6) オブジェクトの型は T である。
  • T が配列型でない場合、オブジェクトは :: new ( pv ) T によって構築される。ここで pv は型 T のオブジェクトを保持するのに適したストレージを指す void * ポインタである。オブジェクトが破棄される場合、 pt - > ~T ( ) によって破棄される。ここで pt は型 T のそのオブジェクトを指すポインタである。
  • T が有界配列型の場合、各要素の初期値は未規定である。
このオーバーロードは、 T が配列型でない場合、または有界配列型である場合にのみ、オーバーロード解決に参加します。
7) オブジェクトの型は std:: remove_extent_t < T > [ N ] です。各要素の初期値は未指定です。
このオーバーロードは、 T が非制限配列型である場合にのみ、オーバーロード解決に参加します。

目次

配列要素の初期化と破棄

以下の説明において、 a は型 Alloc であり、 alloc の潜在的にリバウンドされたコピーである。

U の配列要素は、アドレスの昇順で初期化される。

  • U が配列型でない場合、各要素は以下の式によって構築される。ここで pu は型 std:: remove_cv_t < U > のオブジェクトを保持するのに適したストレージへのポインタであり、 pv は型 U のオブジェクトを保持するのに適したストレージへの void * ポインタである:
2,3) std:: allocator_traits < Alloc > :: construct ( a, pu )
4,5) std:: allocator_traits < Alloc > :: construct ( a, pu, u )
6,7) :: new ( pv ) U
  • それ以外の場合、各要素の要素を再帰的に初期化する。次の次元について:
  • U std:: remove_extent_t < U > となる。
  • オーバーロード (4,5) について、 u u の対応する要素となる。

返される std::shared_ptr によって管理されるオブジェクトの寿命が終了したとき、または配列要素の初期化が例外をスローしたとき、初期化された要素は元の構築順序の逆順で破棄される。

破棄される非配列型 U の各配列要素について、以下の式によって破棄される:

2-5) std:: allocator_traits < Alloc > :: destroy ( a, pu ) 。ここで pu は型 U のその配列要素への U * ポインタである。
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以降)が、 std::allocate_shared はサポートしません。この機能は boost::allocate_shared によってサポートされています。

(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 を構築する
(公開メンバ関数)
新しいオブジェクトを管理する共有ポインタを作成する
(関数テンプレート)