代码之家  ›  专栏  ›  技术社区  ›  Adam Kotwasinski

是否有任何指针包装器可以跟踪原始指针是否被删除?

  •  2
  • Adam Kotwasinski  · 技术社区  · 4 年前

    我正在与API交互,该API将原始指针指向 Thing 有时会自行删除它,基本上是这样的:

    bool foo(Thing* ptr) {
        if (/* some condition */) {
            delete ptr;
            return true;
        } else {
            return false;
        }
    }
    

    现在我正在编写一些与这种方法交互的测试,我想避免编写典型的 T* ptr = new Thing(); bool res = foo(ptr); /* real test */; if (!res) { delete ptr; }; 在代码中传播。

    所以我创建了一种“跟踪包装器”,看起来像这样:

    template <typename T> class Holder {
    public:
    
        // Subclass of Z where the dtor will just update Holder's state.
        template <typename Z> class Helper : public Z {
        public:
            Helper(Holder<Z>& holder): holder_{holder} {}
            virtual ~Helper() { holder_.markDeleted(); }
    
        private:
            Holder<Z>& holder_;
        };
    
        ~Holder() {
            if (!deleted_) { delete ptr; }
        }
    
        void markDeleted() { deleted_ = true; }
        T* data() { return ptr; }
    
    private:
        bool deleted_ = false;
        T* ptr = new Helper<T>(*this);
    };
    

    所以基本上我可以这样使用它:

    Holder<Thing> h;
    foo(h.data());
    

    Holder的析构函数负责清理 Thing* 如有必要。

    此自定义代码是否有其他替代方案(例如在标准库中)?

    我们可以假设如下:

    • T的析构函数是虚的,
    • T不需要构造参数,
    • 我们不能修改T。
    0 回复  |  直到 4 年前
        1
  •  0
  •   Alex Guteniev    4 年前
    auto h = std::make_unique<T>();
    if (foo(h.get())) {
       h.release(); // already deleted, so we don't own it
    }
    

    (这就是为什么实现 不应该 作记号 unique_ptr::release 作为 [[nodiscard]] )