C++中的智能指针

K-R*_*RAN 3 c++ smart-pointers object-destruction object-slicing

假设我们有一个base班级和一个班级derived.所以:

class base {
     protected:
          ~base(){
                //...
          }
     // ...
};

class derived : public base {
     // ...
};
Run Code Online (Sandbox Code Playgroud)

现在说我们使用上面的类和智能指针类有这个代码:

SmartPointer<base> bptr(new derived());
delete bptr;
Run Code Online (Sandbox Code Playgroud)

我知道它会derived通过调用析构函数来阻止对象的切片derived,但它如何知道呢?存储在智能指针中的引用不会是类型的引用base*吗?它是否遍历某种层次结构树,将该指针强制转换为derived*然后调用delete?还是有其他一些我不知道的事情?

该实现被认为是线程安全的,非侵入式的和引用计数.

的,你看到的类类似于我正在测试的类.显然有一种方法可以使用THESE GIVEN课程.关于如何在上面的问题中提到的主要想法,但我不确定这样的实现如何工作.

Dav*_*eas 7

首先,它代表不起作用.析构函数base必须至少protected(或派生类是基础的朋友).一个private析构函数意味着编译器不会让你写的析构函数派生类.现在,假设你有一个protected析构函数...(Rembember,如果你设计一个要扩展的类,提供一个公共虚拟析构函数或一个受保护的非虚函数!)

一切都取决于具体的实施SmartPointer,特别是std::shared_ptr(或者提升对应物boost::shared_ptr)能够干净地管理这种情况.该解决方案执行某种类型的部分类型擦除以用于销毁目的.基本上,智能指针有一个模板化的构造函数,它接受任何可以分配给base指针的指针,但由于它是模板化的,因此它知道具体的类型.此时它存储一个合成deleter函数,该函数将调用适当的析构函数.

为简单起见,使用std::function:

template <typename T>
void delete_deleter( void * p ) {
   delete static_cast<T*>(p);
}

template <typename T>
class shared_pointer {
    T * ptr;
    std::function<void(void*)> deleter;
public:
    template <typename U>
    shared_pointer( U* p, std::function<void()> d = delete_deleter<U> ) 
       : ptr(p), deleter(d)
    {}
    ~shared_pointer() {
       deleter( ptr );  // call the stored destructor
    }
};
Run Code Online (Sandbox Code Playgroud)

代码仅用于展览,它必须进行调整以进行生产(在哪里存储function,引用计数...),但它足以给你一个想法:在唯一的函数中,对象的确切类型是已知(在创建智能指针时),您创建一个包装器,它将调用所需的析构函数的确切版本(提供一些类型的擦除),然后将其保留,当您需要delete对象调用它而不是该delete运营商.

这也可用于管理需要调用特殊方法的其他资源,而不是delete:

// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );
Run Code Online (Sandbox Code Playgroud)

在准备好这个生产之前,应该有相当多的工作.

std::function可以从问题中消除用于简化擦除的依赖性.在简单的情况下(在智能指针中仅支持分配new和释放的内存delete),然后只提供deleter具有单个虚拟的基类operator()(void*),然后使用当前实现delete_deleter从现有的deleter重写中重构现有的模板化派生类operator()(void*).如果你需要寻找一般情况(持有任何类型的资源),那就不值得努力,只需使用std::functionboost::function.