![](/img/trans.png)
[英]Why doesn't aliasing constructor of std::shared_ptr initialize std::enabled_shared_from_this?
[英]Why doesn't std::unique_ptr have an aliasing constructor like std::shared_ptr has?
我剛剛發現了std::shared_ptr
的“別名構造函數”並發現自己在問“為什么std :: unique_ptr沒有相應的一個?
也就是說,如果你想分配一個Foo
以便你可以將它的Bar
成員傳遞給一個完全可以管理Foo
生命周期的函數,那么這樣做是不是很好?
#include <memory>
struct B {}
struct A {
B b;
}
void f(std::unique_ptr<B> b);
std::unique_ptr<A> a = std::make_unique<A>();
std::unique_ptr<B> b { std::move(a), &(a->b) }; // a now invalid.
f(std::move(b)); // f now responsible for deleting the A.
這適用於std :: shared_ptr( http://ideone.com/pDK1bc )
#include <iostream>
#include <memory>
#include <string>
struct B {
std::string s;
};
struct A {
B b;
A(std::string s) : b{s} {};
~A() { std::cout << "A deleted." << std::endl; }
};
void f(std::shared_ptr<B> b) {
std::cout << "in f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
}
int main() {
std::shared_ptr<A> a = std::make_shared<A>("hello");
std::shared_ptr<B> b { a, &(a->b) };
a.reset(); // a now invalid.
std::cout << "before f, b->s = " << b->s << " (use_count=" << b.use_count() << ")" << std::endl;
f(std::move(b)); // f now responsible for deleting the A.
std::cout << "after f" << std::endl;
return 0;
}
輸出預期的
before f, b->s = hello (use_count=1)
in f, b->s = hello (use_count=1)
A deleted.
after f
有沒有合理的理由說明為什么不包含這樣的東西? 和/或,使用帶有刪除A
的自定義刪除器的unique_ptr<B>
來模擬它是不是一個壞主意?
我相信“問題”是,與std::shared_ptr
不同, std::unique_ptr
的刪除器不是類型擦除的。 std::unique_ptr<T>
的默認刪除器(其大小為零,編碼為類型本身作為幾乎不可見的默認類型參數)只是[](T * p){ delete p; }
[](T * p){ delete p; }
。 但很明顯,通過std::make_unique<B>
創建的std::make_unique<B>
和通過指向A
對象的B
成員創建的std::unique_ptr<B>
不能具有相同的刪除器。 后一種情況的刪除器必須做一些指針運算才能獲得原始的A *
指針。 如果兩個刪除器都存儲偏移量或內部指針指向原始對象,那么這兩個刪除器只能具有相同的類型。 那將不再是零大小。 與new
手動delete
和手動delete
相比, std::unique_ptr
開銷設計為零,這是一件好事。 我沒有看到使用你自己的刪除器存儲額外的指針的任何直接的缺點,雖然我仍然需要遇到一個用例,我發現這有用。
shared_ptr
具有引用計數開銷。 在它的引用計數塊中,它還存儲一個顯式的刪除器(因為如果你在堆上存儲,還有幾個字節?)
這也是為什么基類型的shared_ptr
可以記住在沒有虛擬dtor的情況下刪除派生類型的原因。
另一方面, unique_ptr
將其刪除器存儲在實例中,默認刪除器是無狀態的 - 使用0個字節。 這使得unique_ptr
在內存使用方面比原始指針零開銷。
無狀態刪除者不記得刪除別的東西。
您可以向unique_ptr
添加一個支持別名的有狀態刪除器,但是您必須手動設置別名。 其中一個構造函數同時使用指針和刪除器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.