智能指针有真正的用例吗?

now*_*wox -2 c++ pointers smart-pointers

我正在阅读 C++ 中的智能指针,我很惊讶超过 99% 的给定示例实际上是相当糟糕的示例,因为在这些情况下可以避免动态分配。我同意仅在 STL 容器不起作用的上下文中使用智能指针。例如,在动态数组 ( std::vector) 中,性能很重要,因此最好拥有经过良好测试的代码而不使用任何智能指针。

这里我认为是一个不好的例子,因为在这种情况下unique_ptr不是解决方案,但堆栈分配将是正确的方法。

MyObject* ptr = new MyObject(); 
ptr->DoSomething(); 
delete ptr; 
Run Code Online (Sandbox Code Playgroud)

那么什么是 C++ 中智能指针的好例子或用途呢?

换种说法是什么设计模式需要将指针的所有权转移到另一个对象?

ein*_*ica 5

我很惊讶超过 99% 的给定示例实际上是相当糟糕的示例,因为在这些情况下可以避免动态分配

这可能是因为这些示例旨在超级简单。

那么什么是 C++ 中智能指针的好例子或用途呢?

别介意“善良”,但请考虑以下相关案例:

1.当你不能坚持堆栈时

template <typename T>
std::unique_ptr<T[]> print_and_allocate(std::size_t n)
{
    std::cout << "Allocating " << n << " elements of size " << sizeof(T) << '\n';
    return std::make_unique<T[]>(n);
}
Run Code Online (Sandbox Code Playgroud)

您无法在堆栈上执行分配,因为您在使用分配的元素之前返回。此外,您不能只返回单个构造或 an std::array,因为要分配的元素数量事先未知。

2. 需要引用几个可能的子类之一

class A;
class B : public A { /* ... */ };
class C : public A { /* ... */ };

// ...

auto my_a = std::unique_ptr<A>(condition ? (A*) new B : (A*) new C);
my_a.some_virtual_method();
Run Code Online (Sandbox Code Playgroud)

3. 复杂的解除分配逻辑

指针不会告诉您何时/如何释放/释放它。你可以做一个简单的假设(“我需要释放我从这个函数中得到的指针”),但这已经表明在包装类中表达你的假设。如果取消分配的条件更复杂,尤其是如果指针接收者不知道它们,那么以某种方式传达它们就变得至关重要。一个std::shared_ptrstd::weak_ptr是这样做的两种方法;另一个是std::unique_ptr带有自定义删除器的

4. 无法保证未来的可用性时

当指针的提供者不能保证它会继续有效,但预计它可能会是 - 你需要某种包装类来反映这一事实,并确保你不会尝试取消引用指针时你实际上不能。这就是std::weak_ptr()发挥作用的地方。


更一般地说:如果您之前由于某种原因需要分配内存并保存一个指针,并且没有它就无法实现 - 您很可能想改用智能指针。也可以看看:

什么是智能指针,我应该什么时候使用 one (answer)

  • @nowox如果你的类是不可复制和不可移动的,你不能将它放入向量中。此外,由于 unique_ptr 不具备向量的所有功能,因此如果您不需要向量的功能,它的开销可能会更少。 (3认同)