我刚刚发现 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
为什么没有包括这样的东西有合乎逻辑的原因吗?和/或,用 unique_ptr<B>
来模拟它是个坏主意吗?使用删除 A
的自定义删除器?
最佳答案
我认为“问题”在于,与 std::shared_ptr
不同, std::unique_ptr
的删除器没有类型删除。 std::unique_ptr<T>
的默认删除器(它的大小为零,作为几乎不可见的默认类型参数编码到类型本身)只是 [](T * p){ delete p; }
.但很明显,一个std::unique_ptr<B>
这是通过 std::make_unique<B>
创建的和一个通过指向 B
制作的A
的成员对象不能有相同的删除器。后一种情况的删除器必须进行一些指针运算才能获得原始的 A *
。指针返回。如果这两个删除器都将存储一个偏移量或一个指向原始对象的内部指针,那么这两个删除器只能具有相同的类型。那将不再具有零大小。 std::unique_ptr
与 new
相比,设计为零开销和 delete
手动,这是一件好事。我没有看到使用您自己的存储附加指针的删除器有任何直接的缺点,尽管我仍然必须遇到一个我会发现它有用的用例。
关于c++ - 为什么 std::unique_ptr 没有像 std::shared_ptr 那样的别名构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34668918/