名稱空間
變體
操作

std::allocate_shared, std::allocate_shared_for_overwrite

來自 cppreference.com
 
 
記憶體管理庫
(僅作說明*)
未初始化記憶體演算法
(C++17)
(C++17)
(C++17)
受約束的未初始化
記憶體演算法
C 庫

分配器
記憶體資源
垃圾回收支援
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
(C++11)(直到 C++23)
未初始化儲存
(直到 C++20*)
(直到 C++20*)
顯式生命週期管理
 
 
定義於標頭檔案 <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 是一個 void* 指標,指向足以容納 T 型別物件的儲存。如果要銷燬該物件,則其銷燬方式如同 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>* 指標,指向足以容納 std::remove_cv_t<U> 型別物件的儲存,而 pv 是一個 void* 指標,指向足以容納 U 型別物件的儲存
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 所管理的物件生命週期結束時,或當陣列元素的初始化丟擲異常時,已初始化的元素將按照其原始構造順序的逆序被銷燬。

對於要銷燬的每個非陣列型別 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 - 用於初始化陣列中每個元素的初始值

[編輯] 返回值

指向 T 型別物件的 std::shared_ptr,若 T 為無界陣列型別,則為 std::remove_extent_t<T>[N](C++20 起)

對於返回的 std::shared_ptr rr.get() 返回一個非空指標,且 r.use_count() 返回 1

[編輯] 異常

可能丟擲 Alloc::allocate()T 的建構函式所丟擲的異常。如果丟擲異常,(1) 沒有效果。如果在陣列構造過程中丟擲異常,已經初始化的元素將按逆序銷燬(C++20 起)

[編輯] 注意

這些函式通常會分配比 sizeof(T
)
更多的記憶體,以便為內部記賬結構(如引用計數)留出空間。

std::make_shared 類似,此函式通常只執行一次分配,並將 T 物件和控制塊都放在分配的記憶體塊中(標準推薦但不強制要求這樣做,所有已知的實現都這樣做)。alloc 的一個副本作為控制塊的一部分儲存,以便在共享和弱引用計數都達到零時用於釋放記憶體。

std::shared_ptr建構函式不同,std::allocate_shared 不接受一個獨立的自定義刪除器:提供的分配器用於銷燬控制塊和 T 物件,以及釋放它們共享的記憶體塊。

std::shared_ptr 支援陣列型別(自 C++17 起),但 std::allocate_shared 不支援。此功能由 boost::allocate_shared 支援。

(C++20 前)

一個建構函式使用型別為 U* 的指標 ptr啟用 shared_from_this” 是指,它確定 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_overwritestd::make_shared_for_overwritestd::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()
{
    // Create a polymorphic allocator using the monotonic buffer resource
    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)
        // Use std::allocate_shared with the custom allocator
        v.emplace_back(std::allocate_shared<Value>(allocator, i));
 
    for (const auto& sp : v)
        sp->print();
} //< All shared pointers will automatically clean up when they go out of scope.

輸出

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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 3216 C++20 std::allocate_shared 在構造和銷燬物件前總是重繫結
分配器
重繫結是可選的
LWG 4024 C++20 不清楚在 std::allocate_shared_for_overwrite
構造的物件如何被銷燬
已明確

[編輯] 參閱

構造新的 shared_ptr
(公開成員函式) [編輯]
建立一個管理新物件的共享指標
(函式模板) [編輯]
English 日本語 中文(简体) 中文(繁體)