【发布时间】:2010-10-08 08:21:34
【问题描述】:
我正在使用的代码有自己的智能指针实现,它执行简单的引用计数。是的,我们不应该有自己的实现。是的,我们应该使用 boost 中的一个或类似的。忍受我。
我发现我想写这样的代码:
...
CountedPointer<Base> base;
...
CountedPointer<Derived> derived;
...
base = derived;
但是,CountedPointer 的复制构造函数有一个这样的原型:
CountedPointer(const CountedPointer<T> &other);
所以上面的代码无法编译,因为它找不到合适的构造函数(或赋值运算符 - 那里是同样的故事)。我尝试用这样的原型重写复制构造函数:
template<U>
CountedPointer(const CountedPointer<U> &other);
但是,我遇到了一个问题,即复制构造函数必须访问它正在复制的对象的私有成员(即原始指针),并且如果它处于不同的 CountedPointer 特化中,它们是不可见的。
Alexandrescu 在他的库 Loki 中通过封装指针的访问器函数避免了这个问题,但如果可能的话,我不希望直接访问原始指针。
我有什么办法可以写这个来允许派生到基础副本,但不允许一般访问原始指针?
更新: 我已经实现了下面接受的答案,并且效果很好。当我只提供复制构造函数的模板版本,替换原始的未模板版本时,我花了一段时间弄清楚为什么我的程序会出现可怕的段错误。最终,我意识到编译器并不将模板化版本视为复制构造函数,而是提供了一个默认版本。默认的只是愚蠢地复制内容而不更新计数器,所以我最终得到了悬空指针和双重释放。同样的事情也适用于赋值运算符。
【问题讨论】:
-
很难阻止对原始指针的访问。 &*CounterPointer
() 通常是原始 T*。不过,它不适用于空指针。 -
我觉得提供一个函数作为接口的一部分表明使用原始指针是个好主意。如果有人决定他们需要获取原始指针,他们无论如何都会修改接口。这是很小的;如果它是我的代码,它不会打扰我太多。
标签: c++ smart-pointers