是否有/应该有一种方法可以跟踪从智能指针获取的原始指针的有效性,以进行调试/ QA?

时间:2019-05-11 19:58:10

标签: c++ c++11 c++14 smart-pointers defensive-programming

据我所知C++ Core Guidelines by Bjarne Stroustrup & Herb Sutter,以这种方式使用指针是一个好主意:

  • unique_ptr可以清除旧的所有权
  • shared_ptr通过设计实现真正的共享所有权
  • weak_ptr,根据设计,指针可能不再有效
  • 只要指针在设计上有效且所有权不变,就可以原始指针

因此,从理论上讲,原始指针可能仍然是一个常见的错误(请参见R37)。
我想知道是否有一种用于调试/ QA目的的方法来断言原始指针的有效性。我相信这样的检查可以帮助大大提高程序的稳定性。

我写了以下可能的实现。我的问题:
您对拥有这样的代码有什么看法?这对您有意义吗?是否存在这样的东西?还有其他评论吗?

在此阶段,实现的完整性并不那么重要(线程安全性或其他方面),除非它反映了不这样做的原因。

#include <memory>
#include <cassert>

#if NDEBUG

template <typename T>
using WatchedPtr = T*;

template <typename T>
T* get (const std::shared_ptr<T>& p) {return p.get();}

#else

template <typename T>
class WatchedPtr {
    template <typename T1>
    friend WatchedPtr<T1> get (const std::shared_ptr<T1>& p);

public:
    WatchedPtr() : _ptr (nullptr) {}

    operator T* () { return getPtr();}

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

    T& operator*() const { assert (getPtr()); return *getPtr(); }

private:
    T* getPtr () const { return _weak.expired () ? nullptr : _ptr;}
    WatchedPtr(std::shared_ptr<T> p) : _weak (p) {
        _ptr = _weak.lock().get();
    }
    std::weak_ptr<T> _weak;
    T* _ptr;
};

template <typename T1>
inline WatchedPtr<T1> get (const std::shared_ptr<T1>& p) {return WatchedPtr<T1> (p);} //because I cannot change the get() member

#endif

用法示例:

void f (WatchedPtr<int> p) {
    assert(p);//detects errors
    *p = 3;//detects errors
    std::cout << "f: *p=" << *p << std::endl;
}

void g (int* p) {
    assert(p);//detects errors
    *p = 3;//does not detect error
    std::cout << "g: *p=" << *p << std::endl;
}

int main () {
    WatchedPtr<int> p;

    {
        auto pp = std::make_shared<int> (1234);
        p = get(pp);
        f (p);
    }
    f (p);
    g (p); //the internal assert() of g() will detect errors, because casting of invalid p to raw pointer will be nullptr
}

*我想过也要为unique_ptr实现。但是到目前为止,我唯一的想法是在WatchedPtr中存储一个指向unique_ptr的指针。这只会在某些情况下识别错误,其中get()或bool运算符将崩溃或返回nullptr。

0 个答案:

没有答案
相关问题