c++ - 为什么原始指针没有 "weak pointer"?或者有吗?

标签 c++ c++11 smart-pointers

毫无疑问,共享指针是个好主意。但只要大型程序包含原始指针,我认为使用共享指针就有很大的风险。主要是,您将失去对指向包含原始指针的对象的指针的真实生命周期的控制,并且错误将出现在更难以查找和调试的位置。

所以我的问题是,是否没有尝试向现代 c++ 添加一个不依赖于使用共享指针的“弱指针”?我的意思是只是一个指针,当在程序的任何部分删除时它会变成 NULL。有理由不使用这种自制的 wrapper 吗?

为了更好的解释我的意思,下面是我做的这样一个“弱指针”。我将其命名为 WatchedPtr。

#include <memory>
#include <iostream>

template <typename T>
class WatchedPtr {
public:
    // the only way to allocate new pointer
    template <typename... ARGS>
    WatchedPtr(ARGS... args) : _ptr (new T(args...)), _allocated (std::make_shared<bool>(true)) {}

    WatchedPtr(const WatchedPtr<T>& other) : _ptr (other._ptr), _allocated (other._allocated) {}

    // delete the pointer
    void del () {delete _ptr; *_allocated = false;}

    auto& operator=(const WatchedPtr<T> &other) { return *this = other; }

    bool isNull() const { return *_allocated; }

    T* operator->() const { return _ptr; }

    T& operator*() const { return *_ptr; }

private:
    T* _ptr;
    std::shared_ptr <bool> _allocated;
};

struct S {
    int a = 1;
};

int main () {
    WatchedPtr<S> p1;
    WatchedPtr<S> p2(p1);
    p1->a = 8;
    std::cout << p1.isNull () << std::endl;
    std::cout << p2.isNull () << std::endl;
    p2.del ();
    std::cout << p1.isNull () << std::endl;
    std::cout << p1.isNull () << std::endl;
    return 0;
}

结果:

1
1
0
0

-已编辑-

谢谢大家。到目前为止的评论和答案之后的一些澄清:

  • 我为 WatchedPtr 提供的实现只是为了演示我的意思:一个指针,它不会从外部分配中获取拷贝,不能从外部删除,如果删除则变为 null。众所周知,实现远非完美,也不意味着完美。
  • 混合使用 shared_ptr 和原始指针的问题非常普遍:A* 被保存为原始指针,因此在程序的某些位置创建并在程序的某些位置显式删除。 B 持有一个 A*,而 B* 持有为 shared_ptr,因此 B* 具有模糊的生命周期。因此,B 可能在 B 持有的 A* 被删除后存活很长时间。
  • 在我看来“WatchedPtr”的主要用途是防御性编程。即检查 null 并为连续性做最好的事情(和调试错误)。 shared_ptr 可以做到,但是以一种非常危险的方式 - 它会隐藏和延迟问题。
  • “WatchedPtr”(很少且明确的“所有者”)也可以有设计用法,但这不是主要思想。因为确实共享指针正在做这项工作。
  • “WatchedPtr”的目的不是一次性替换程序中所有现有的原始指针。这与替换为 shared_ptr 的工作不同,恕我直言,它已为整个程序一次性完成。这对于大型项目来说是不现实的。

最佳答案

弱指针依赖于来自智能指针基础设施的通知,因此您永远无法使用实际的原始指针来做到这一点。

当然,可以想象 unique_ptr 的扩展支持弱指针。据推测,没有人急于实现这样一个特性的主要原因是弱指针已经处于“使用引用计数,一切都应该正常工作”的末尾,而 unique_ptr 处于“管理你的通过 RAII 的生命周期,或者你不是真正的 C++ 程序员”。弱指针还要求每个分配有一个单独的控制 block ,这意味着与 shared_ptr 相比,这种 WatchedPtr 的性能优势将是最小的。

关于c++ - 为什么原始指针没有 "weak pointer"?或者有吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55500183/

相关文章:

c++ - 如何使用 C++11 创建高效的闭包?

c++ - 具有隐式转换的模板函数参数推导

c++ - boost::scoped_ptr 是否违反逻辑常量准则

c++ - 引用 vector 中的对象(现代 C++)

c++ - 如何将复杂的指针数据作为属性放入 qt 插件 xml 文件中

c++ - 在 C++ 中增加循环队列的容量

c++ - 候选函数不可行 : expects an l-value for 3rd argument

c++ - unique_ptr : How to safely share raw pointer

C++ 安全对象删除

c++ - 如何知道源文件属于哪个项目?