我想深入了解C++。STL中有一些我想理解的决策,仅仅从代码来看就很难理解。
我的想法是自己实现一些STL,以了解其中的陷阱,从而提高我对C++的理解并改进我的代码。我希望STL容器中有一些STD没有的功能,比如资源处理类的销毁通知。我创建了SharedPointer的扩展版本,其中包含一个std::函数作为删除通知程序。
我发现了一些麻烦。
以以下代码为例:SmartPointer.hpp
这是我想出的一些代码,并且有一些问题。
做空:
- 已知问题
- 派生类不起作用
- 抱怨类型不完整
- 未知问题
长:
1.1.派生类不起作用
在类型被强制转换之后,仅仅将T作为类型是不起作用的。我们的想法是将OrigT作为第二个参数传递,这样我就可以随时知道ptr指向什么类型。我可以将其反向转换并调用正确的析构函数。
考虑
SharedPointer<Derived> member = base.Cast<Derived>();
将创建T=OrigT,并且类型在断言上强制转换后将不匹配。我无法想象我怎么能解决这个问题。
if (!shared->HasReferences())
{
delete shared;
OriginalValuePointer origPtr = dynamic_cast<OriginalValuePointer>(ptr);
delete origPtr;
}
1.2.抱怨类型不完整
在我的例子中,我收到了关于不完整类型的抱怨。但我不明白为什么。目前我正在考虑制作运算符*和运算符->模板,这将是一个黑暗中的镜头。我不知道它为什么会抱怨,我想问你是否可以指出这里的问题。
Same code as above in compiler complaint
2.2.我认为stackoverflow不是寻求反馈的理想场所,但考虑到我的两个问题,我还是想问一下。
是否有人拥有可读的任何来源,以及理想解释的智能指针?我发现的那些并不完全符合我的期望。它们要么过于简单,要么在关键点没有包含解释。
我非常感谢对代码的一些直接反馈。当然来自编码风格;-(。你有没有直接看到我犯了什么错误我会后悔?还有什么可以做得更好的吗?(例如,.Cast as member是IMHO的一个糟糕选择。这一次,它不是指针的直接属性,我认为它可能会导致我还不知道的缺陷。(
我非常感谢你的帮助和意见。
保持健康。
- 普通C++类使用snake_case,而不是CamelCase
- 这个类不是线程安全的(你可能知道,但值得一提(
- NumReferences通过引用返回计数,这并不有用,并且比通过
int
返回的速度稍慢 - 类中定义的所有方法都是自动
inline
,所以在任何地方都不需要它 operator ValueType()
是隐含的,这是超级危险的。你可以把它说得很清楚,但我会把它完全删除operator ValueType()
需要知道ValueType
的详细信息才能被创建。因此,如果ValueType
还没有完全定义,您将得到关于不完整类型的编译器错误。同样,删除该方法可以消除此问题- CCD_ 7和CCD_。首选
explicit
- 强烈考虑将
assert
添加到所有使用shared
或ptr
的方法中,而不首先检查它是否为null
Raw()
通常命名为get()
现在,转到OrigT
和Release
:std::shared_ptr
做了一个有趣的技巧,其中SharedData
具有继承性:
struct SharedData {
std::atomic_uint count;
virtual ~SharedData() {}
};
template<class OrigT>
struct SharedDataImpl {
OrigT* data;
~SharedData() {delete data;}
};
由于同一数据的所有shared_ptr都指向同一个SharedDataImpl,因此它们不必知道派生程度最高的类。他们所要做的就是删除SharedData成员,它会自动正确地清理数据。这确实需要有第二个数据指针:一个在SharedPointer
本身,一个在SharedData
,但通常这不是问题。(或virtual T* get()
方法(