我想要一个类似于boost scoped_ptr
的安全C ++指针容器,但是具有类似于值的复制语义。我打算在应用程序的最内层循环中将这个用于非常少使用的类的极少使用的元素,以获得更好的内存局部性。换句话说,只要它的“内联”内存负载很小,我就不关心这个类的性能。
我从以下开始,但我不擅长这个;以下是安全的吗?我是否重新发明轮子,如果是这样,我应该在哪里看?
template <typename T>
class copy_ptr {
T* item;
public:
explicit copy_ptr() : item(0) {}
explicit copy_ptr(T const& existingItem) : item(new T(existingItem)) {}
copy_ptr(copy_ptr<T> const & other) : item(new T(*other.item)) {}
~copy_ptr() { delete item;item=0;}
T * get() const {return item;}
T & operator*() const {return *item;}
T * operator->() const {return item;}
};
编辑: 是的,这是故意的,它的行为与正常值非常相似。分析表明该算法在其他方面相当有效,但有时会因缓存未命中而受到阻碍。因此,我试图通过提取当前包含在值中但实际上并未在最内层循环中使用的大blob来减小对象的大小。我宁愿在没有语义变化的情况下这样做 - 一个简单的模板包装器将是理想的。
答案 0 :(得分:5)
不,不是。
您忘记了作业操作员。
您可以选择禁止分配(允许复制时很奇怪),方法是将分配操作员声明为私有(而不是实现),或者您可以这样实现:
copy_ptr& operator=(copy_ptr const& rhs)
{
using std::swap;
copy_ptr tmp(rhs);
swap(this->item, tmp.item);
return *this;
}
您还忘记了复制构造函数中other.item
可能为null(作为默认构造函数的结果),请选择您的替代方法:
// 1. Remove the default constructor
// 2. Implement the default constructor as
copy_ptr(): item(new T()) {}
// 3. Implement the copy constructor as
copy_ptr(copy_ptr const& rhs): item(other.item ? new T(*other.item) : 0) {}
对于类似于值的行为,我更喜欢2
,因为值不能为空。如果您允许无效,请在assert(item);
和operator->
中引入operator*
以确保正确性(在调试模式下)或抛出异常(无论您喜欢什么)。
最后析构函数中的item = 0
是无用的:无论如何在不调用未定义的行为的情况下都无法使用该对象......
还有罗杰佩特关于常数传播的评论更像“价值”,但它更多的是语义而不是正确性。
答案 1 :(得分:3)
你应该“传递”copy_ptr类型的常量:
T* get() { return item; }
T& operator*() { return *item; }
T* operator->() { return item; }
T const* get() const { return item; }
T const& operator*() const { return *item; }
T const* operator->() const { return item; }
复制文件中不需要指定T:
copy_ptr(copy_ptr const &other) : item (new T(*other)) {}
为什么要将默认ctor显式化?如果你计划某个地方的UB,那么在dtor中取消指针只是有意义的......
但这些都是小问题,你所拥有的几乎就是它。是的,我已经看过很多次发明,但人们倾向于每次稍微调整一下语义。您可以查看boost :: optional,因为除非您添加移动语义和其他操作,否则这几乎是您在演示时所写的内容。
答案 2 :(得分:1)
除了Roger所说的,你可以谷歌'clone_ptr'进行创意/比较。