好的设计?用于分配的智能指针与用于访问的原始指针相结合

Good design? Smart pointers for allocation combined with raw pointers for access

我正在设计一个 FilterData class 读取自定义二进制数据文件并在内存中构建它的数据模型。我想使用智能指针分配所有内存,让这个 FilterData 拥有数据的所有权。当调用者需要访问数据时,它只会从 FilterData 实例中获取原始指针。

您认为这是好的设计吗?或者作为程序员您会觉得 "mixture" 令人困惑吗?

一些想法:

  1. 为什么使用原始指针? 我需要与使用原始 float* 的现有 API 进行交互。此外,我强调调用者不拥有分配的内存。我的大多数 "clients" 都是在处理智能指针方面经验不足的编码人员。

  2. 如果我需要一份数据的副本,我可以用 return std::unique_ptr 的副本扩展 FilterData 相应的功能(因此转移所有权副本)。

  3. 作为一个可能的危险,我看到有人可以在 returned 指针上调用 delete,但是由于我计划使用智能指针进行所有内存分配,任何 delete无论如何都会出错。

下面是一些示例代码:

#include <iostream>
#include <vector>
#include <string>
#include <memory>

class FilterData
{
  using fvec = std::vector<float>;
public:
  FilterData(const std::string& filename) {
    // (simulate read from file...)
    m_filterACoeffs = std::make_unique<fvec>();
    m_filterBCoeffs = std::make_unique<fvec>();
    m_filterACoeffs->emplace_back(1.f); m_filterACoeffs->emplace_back(2.f); m_filterACoeffs->emplace_back(3.f);
    m_filterBCoeffs->emplace_back(-1.f); m_filterBCoeffs->emplace_back(-2.f); m_filterBCoeffs->emplace_back(-3.f);
  }
  const fvec* getFilterACoeffs() { return m_filterACoeffs.get(); }
  const fvec* getFilterBCoeffs() { return m_filterBCoeffs.get(); }

private:
  std::unique_ptr<fvec> m_filterACoeffs;
  std::unique_ptr<fvec> m_filterBCoeffs;

};

int main() 
{
  FilterData filterData("thefile.bin");
  auto p_filterACoeffs = filterData.getFilterACoeffs();
  auto p_filterBCoeffs = filterData.getFilterBCoeffs();

  std::cout << "Filter A is: " << p_filterACoeffs->at(0) << " , " 
                               << p_filterACoeffs->at(1) << " , " 
                               << p_filterACoeffs->at(2) << std::endl; 

  std::cout << "Filter B is: " << p_filterBCoeffs->at(0) << " , " 
                               << p_filterBCoeffs->at(1) << " , " 
                               << p_filterBCoeffs->at(2) << std::endl; 
}

在转让所有权时使用并公开 unique_ptr。当所有权是公共的时使用 shared_ptr。定义函数以获取原始指针或引用,前提是它们不参与所有权。

在您的情况下,使用 unique_ptr 但不要公开它或访问它的方法。你做到了,对你很好。公开原始指针,根据需要进行构造,如果有人想对其调用 delete,嘿,他们瞄准的是他们的脚。我宁愿以一种需要更少输入的方式公开原始指针。

2014 年 CPP Con 的这段演讲指出了这一点:https://youtu.be/xnqTKD8uD64?t=12m10s(我知道链接是邪恶的,但我怀疑这个链接会一直存在到自由女神像齐胸深的沙子中。)