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

C++ 好的设计?用于分配的智能指针与用于访问的原始指针相结合,c++,c++11,memory-management,smart-pointers,C++,C++11,Memory Management,Smart Pointers,我正在设计一个FilterData类,它读取自定义二进制数据文件,并在内存中构建该文件的数据模型。我想使用智能指针分配所有内存,并让这个FilterData拥有数据的所有权。当调用者需要访问数据时,它只会从FilterData实例获取一个原始指针 你认为这是一个好的设计吗?或者作为一个程序员,你会觉得这种“混合”令人困惑吗 一些想法: 为什么是原始指针?我需要与使用原始float*的现有API接口。此外,我强调调用方并不拥有分配的内存。我的大多数“客户”都是程序员,他们在处理智能指针方面没有那么

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

你认为这是一个好的设计吗?或者作为一个程序员,你会觉得这种“混合”令人困惑吗

一些想法:

  • 为什么是原始指针?我需要与使用原始
    float*
    的现有API接口。此外,我强调调用方并不拥有分配的内存。我的大多数“客户”都是程序员,他们在处理智能指针方面没有那么丰富的经验

  • 如果需要数据的副本,我可以使用相应的函数扩展
    FilterData
    ,这些函数返回带有副本的
    std::unique_ptr
    (从而转移副本的所有权)

  • 作为一种可能的危险,我发现有人可以对返回的指针调用
    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; 
    }
    
    #包括
    #包括
    #包括
    #包括
    类过滤器数据
    {
    使用fvec=std::vector;
    公众:
    FilterData(常量std::字符串和文件名){
    //(模拟从文件读取…)
    m_filteracoefs=std::make_unique();
    m_filterbcoefs=std::make_unique();
    m_Filteracefs->emplace_back(1.f);m_Filteracefs->emplace_back(2.f);m_Filteracefs->emplace_back(3.f);
    m_FilterbCoefs->emplace_back(-1.f);m_FilterbCoefs->emplace_back(-2.f);m_FilterbCoefs->emplace_back(-3.f);
    }
    常量fvec*getFilteracefs(){返回m_filteracefs.get();}
    常量fvec*getFilterbCoefs(){返回m_FilterbCoefs.get();}
    私人:
    标准::唯一的过滤器系数;
    标准:唯一的过滤器系数;
    };
    int main()
    {
    FilterData FilterData(“thefile.bin”);
    auto p_Filteracefs=filterData.GetFilteracefs();
    auto p_FilterbCoefs=filterData.GetFilterbCoefs();
    
    std::cout当所有权是要转移的对象时,使用并公开unique_ptr。当所有权是公共的时,使用shared_ptr。定义函数以获取未参与所有权的原始指针或引用

    在您的情况下,请使用unique_ptr,但不要公开它或访问它的方法。您做得很好。公开原始指针,根据需要进行配置,如果有人想在其上调用delete,嘿,这是他们的目标。我更希望以不需要太多键入的方式公开原始指针


    2014年CPP大会上的这篇演讲明确了这一点:(我知道链接是邪恶的,但我怀疑这一链接会一直存在,直到自由女神像在沙子里沉到胸前。)

    原始的非所有权指针是可以的(只要生命是正确的).
    std::share_ptr
    /
    std::unique_ptr
    可能会提供更多的保证。在您的示例中,返回引用似乎更合适。顺便说一句,这是代码评审的主题
    std::vector
    并不是与
    std::unique_ptr
    一起使用的最佳示例,因为
    vector
    本身就足够了。对于工作代码/评审而言,请求se发帖:谢谢你的链接-看来我的思路是对的:-)