c++ - 为什么 std::unique_ptr 没有像 std::shared_ptr 那样的别名构造函数?

标签 c++ c++11

我刚刚发现 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_ptrnew 相比,设计为零开销和 delete手动,这是一件好事。我没有看到使用您自己的存储附加指针的删除器有任何直接的缺点,尽管我仍然必须遇到一个我会发现它有用的用例。

关于c++ - 为什么 std::unique_ptr 没有像 std::shared_ptr 那样的别名构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34668918/

相关文章:

c++ - 如何在 Visual Studio 2010 中添加 Poco 库?

c++ - 如何从函数内部修改作用域变量?

c++ - boost::atomic 真的可以通过减少多线程系统调用(在互斥/信号量中)的开销来 boost 性能吗?

c++11 - Cython:避免通过 std::move 复制不起作用

c++ - 如何在 C++ 中寻找特定行以附加数据或将数据附加到最后一行

c++ - 是否可以从可执行文件中取消链接目标文件

c++ - 从外部类 C++ 正确调用嵌套类中的函数

c++ - 为什么编译器需要复制构造函数,需要并拥有移动构造函数而不使用它们中的任何一个?

c++ - 如何改进使用单例模式的消息传递系统?

c++ - using-style 和 typedef-style 有什么区别?