首页 > 解决方案 > 如何改进作为类成员变量的智能指针的取消引用

问题描述

我有以下类结构 -

typedef std::shared_ptr<Inner> InnerPtr;
class Outer {
   private:
      const InnerPtr ptr_;

   public:
      Outer(const InnerPtr& ptr) : ptr_(ptr) {} 
      int calculate(int id) {
           return ptr_->calculate_other(id);
      }
}

在这里,Outer::calculate()可能会被调用很多次(以百万为单位)。

由于每次调用Outer::calculate()dereferences ptr_,我认为与仅使用对象相比,它会对性能产生影响。

所以我想出了这个-

typedef std::shared_ptr<Inner> InnerPtr;
class Outer {
   private:
      Inner& obj_;    // to reference *ptr_
      const InnerPtr ptr_;  // still need to hold a copy of smart pointer to ensure obj stays in memory during the lifetime of Outer
      
   public:
      Outer(const InnerPtr& ptr) : ptr_(ptr), obj_(*ptr) {} 
      int calculate(int id) {
           return obj.calculate_other(id);
      }
}

我不确定这是否是最好的解决方案。我正在寻找改进calculate功能的建议。

注意:假设ptr传递给Outer()的是一个非空共享指针

标签: c++referencec++14shared-ptrsmart-pointers

解决方案


引用通常在 C++ 中作为硬件级别的指针实现,当它不能完全删除时(因为在逻辑上它是一个别名)。从类的主体中删除引用非常困难;我不知道有一个编译器会尝试(除了在某些情况下可能完全消除类实例)。

Inner const&就生成的程序集而言,遵循 a和 a之间的区别shared_ptr<Inner const>const基本上没有什么区别。

现在,您误解了如何const工作;const InnerPtr是指向非 const 值的 const 指针,const Inner&而是对 const 值的引用。但我认为这不是故意的。

现在, aFoo&类似于 a Foo* const,因此顶层 const可能会以某种方式导致一些优化;您不得更改任何一点的位置。这可能导致编译器能够证明 aFoo&在两位代码中引用同一个对象,但无法证明 aFoo*确实如此。

但是,在您的示例中,您有一个const shared_ptr,它也有顶级const

一般来说,过早的优化是万恶之源。但是过早的悲观化(优化的反面)也是如此。遵循智能指针并不是过早的加压,您的参考优化是过早优化的一个例子。只有当您已经确定存在性能瓶颈时,您才应该考虑进行此类更改。


Outer老实说,当您从右值共享 ptr构建类时,您更有可能遇到由构造函数中无关引用计数增加引起的问题,而不是您发现的问题。更重要的是,额外的原子引用计数将导致扩散减速,因为原子操作同步不会导致代码运行时的大部分减速,而是会破坏 CPU 缓存并使程序的其余部分慢点。

所以改变这个:

explicit Outer(InnerPtr ptr) : ptr_(std::move(ptr)) {} 

消除悲观情绪;现在:

Outer outer( GenerateInnerPtr() );

引用计数的增加和减少比以前少 1,并且没有其他情况导致更多的引用计数增加/减少。


推荐阅读