简体   繁体   English

这个C ++指针容器安全吗?

[英]Is this C++ pointer container safe?

I want a safe C++ pointer container similar to boost's scoped_ptr , but with value-like copy semantics. 我想要一个与boost的scoped_ptr类似的安全C ++指针容器,但具有类似值的复制语义。 I intend to use this for a very-rarely used element of very-heavily used class in the innermost loop of an application to gain better memory locality. 我打算将其用于应用程序最内层循环中非常常用的类中非常常用的元素,以获取更好的内存局部性。 In other words, I don't care about performance of this class so long as its "in-line" memory load is small. 换句话说,只要它的“内联”内存负载很小,我就不会在意此类的性能。

I've started out with the following, but I'm not that adept at this; 我从以下内容开始,但是我对此并不熟练。 is the following safe? 以下安全吗? Am I reinventing the wheel and if so, where should I look? 我是在重新发明轮子吗?如果是,我应该去哪里找?

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;}
};

Edit: yes, it's intentional that this behaves pretty much exactly like a normal value. 编辑:是的,这是故意的,它的行为几乎与正常值完全一样。 Profiling shows that the algorithm is otherwise fairly efficient but is sometimes hampered by cache misses. 分析表明,该算法在其他方面相当高效,但有时会因高速缓存未命中而受阻。 As such, I'm trying to reduce the size of the object by extracting large blobs that are currently included by value but aren't actually used in the innermost loops. 因此,我试图通过提取当前包含在值中但实际上未在最内层循环中使用的大blob来减小对象的大小。 I'd prefer to do that without semantic changes - a simple template wrapper would be ideal. 我更愿意在不进行语义更改的情况下进行操作-一个简单的模板包装器将是理想的选择。

No it is not. 不它不是。

You have forgotten the Assignment Operator. 您忘记了赋值运算符。

You can choose to either forbid assignment (strange when copying is allowed) by declaring the Assignment Operator private (and not implementing it), or you can implement it thus: 您可以通过将Assignment Operator声明为私有(而不是实现它)来选择禁止分配(允许复制时很奇怪),也可以这样实现:

copy_ptr& operator=(copy_ptr const& rhs)
{
  using std::swap;

  copy_ptr tmp(rhs);
  swap(this->item, tmp.item);
  return *this;
}

You have also forgotten in the copy constructor that other.item may be null (as a consequence of the default constructor), pick up your alternative: 您还已经在副本构造函数中忘记了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) {}

For value-like behavior I would prefer 2 , since a value cannot be null. 对于类似值的行为,我希望使用2 ,因为值不能为null。 If you go for allowing nullity, introduces assert(item); 如果允许无效,请引入assert(item); in both operator-> and operator* to ensure correctness (in debug mode) or throw an exception (whatever you prefer). operator->operator*可以使用,以确保正确性(在调试模式下)或引发异常(无论您喜欢什么)。

Finally the item = 0 in the destructor is useless: you cannot use the object once it's been destroyed anyway without invoking undefined behavior... 最终析构函数中的item = 0是无用的:一旦销毁了对象,就无法使用它,而无需调用未定义的行为...

There's also Roger Pate's remark about const-ness propagation to be more "value-like" but it's more a matter of semantics than correctness. 还有罗杰·佩特(Roger Pate)关于常量性传播更像“价值样”的言论,但这更多是语义问题,而不是正确性。

You should "pass on" the const-ness of the copy_ptr type: 您应该“传递” 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; }

Specifying T isn't needed in the copy ctor: 复制代码中不需要指定T:

copy_ptr(copy_ptr const &other) : item (new T(*other)) {}

Why did you make the default ctor explicit? 为什么要使默认ctor明确? Nulling the pointer in the dtor only makes sense if you plan on UB somewhere... 仅当您计划在某个地方的UB时,才将dtor中的指针调零才有意义...

But these are all minor issues, what you have there is pretty much it. 但这都是小问题,您所拥有的几乎全部。 And yes, I've seen this invented many times over, but people tend to tweak the semantics just slightly each time. 是的,我已经看过很多次发明了这种发明,但是人们往往每次都会稍微调整一下语义。 You might look at boost::optional, as that's almost what you have written here as you present it, unless you're adding move semantics and other operations. 您可能会看一下boost :: optional,因为这几乎是您在此处介绍的内容,除非您要添加移动语义和其他操作。

除了罗杰(Roger)所说的之外,您还可以通过Google'clone_ptr'获得想法/比较。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM