C++ 使用唯一的ptr和适当的容器进行内存管理

C++ 使用唯一的ptr和适当的容器进行内存管理,c++,c++11,memory-management,containers,smart-pointers,C++,C++11,Memory Management,Containers,Smart Pointers,首先,我的动机是在类似C的计算内核上进行有效的内存管理。我尝试使用std::unique\u ptr和std::vector,我的代码如下所示 // my data container typedef std::unique_ptr<double> my_type; std::vector<my_type> my_storage; // when I need some memory for computation kernel my_storage.push_back

首先,我的动机是在类似C的计算内核上进行有效的内存管理。我尝试使用
std::unique\u ptr
std::vector
,我的代码如下所示

// my data container
typedef std::unique_ptr<double> my_type;
std::vector<my_type> my_storage;

// when I need some memory for computation kernel
my_storage.push_back(my_type());
my_storage.back.reset(new double[some_length]);

// get pointer to do computational stuff
double *p_data=my_storage.back.get();
//我的数据容器
typedef std::唯一的\u ptr我的\u类型;
std::向量my_存储;
//当我需要一些计算内核的内存时
my_storage.push_back(my_type());
my_storage.back.reset(新的双精度[某些长度]);
//获取指针来执行计算任务
double*p_data=my_storage.back.get();
请注意,在实践中,p_数据可以存储在其他容器中(例如map),以便根据域问题对每个分配的数组进行索引,然而,我的主要问题是

  • 以下是
    std::vector
    一个不错的选择?其他容器如
    std::list
    /
    set

  • 我的分配方法存在根本问题吗

  • 假设在我为一些操作使用p_数据之后,现在我想释放原始指针p_数据所指向的内存块,这里的最佳实践是什么


  • 首先,如果要分配数组,则需要使用专用化
    std::unique\u ptr
    ,否则在释放内存时不会得到
    delete[]
    ,而是得到一个简单的
    delete

    std::vector
    是一个不错的选择,除非您有明确的理由使用不同的东西。例如,如果要在容器中移动多个元素,则
    std::list
    可以执行更好的操作(减少
    memmove
    操作来移动内容)

    关于如何管理内存,这主要取决于使用模式。如果
    my_storage
    主要负责所有事情(在您的规范中,它是唯一的,因为
    unique\u ptr
    表示所有权),这意味着它将是唯一可以释放内存的存储设备。只需调用
    my_storage[i].reset()
    即可完成此操作

    请注意,如果释放内存,将托管对象的原始指针存储在其他集合中会导致指针悬空,例如:

    using my_type = std::unique_ptr<double[]>;
    using my_storage = std::vector<my_type>;
    
    my_storage data;
    data.push_back(my_type(new double[100]));
    
    std::vector<double*> rawData;
    rawData.push_back(data[0].get());
    
    data.clear(); // delete [] is called on array and memory is released
    *rawData[0] = 1.2; // accessing a dangling pointer -> bad
    

    通常,对任何STL容器(包括
    std::vector
    )使用
    std::unique\u ptr
    )都可以。但是,您没有以正确的方式使用
    std::unique_ptr
    (您没有使用它的阵列专用版本),并且根本不需要使用
    back.reset()
    。请尝试以下方法:

    // my data container
    typedef std::unique_ptr<double[]> my_type;
    // or: using my_type = std::unique_ptr<double[]>;
    
    std::vector<my_type> my_storage;
    
    my_type ptr(new double[some_length]);
    my_storage.push_back(std::move(ptr));
    // or: my_storage.push_back(my_type(new double[some_length]));
    // or: my_storage.emplace_back(new double[some_length]);
    
    //我的数据容器
    typedef std::唯一的\u ptr我的\u类型;
    //或者:使用my_type=std::unique_ptr;
    std::向量my_存储;
    my_type ptr(新双精度[某些长度]);
    my_storage.push_back(std::move(ptr));
    //或者:my_storage.push_back(my_type(新的双精度[some_length]);
    //或者:我的存储。放置回(新的双[一些长度]);
    
    如果希望在不同容器之间共享
    p_数据
    ,则可以使用
    std::shared_ptr
    ,然后根本不使用原始指针。
    std::unique_ptr
    ,如果使用
    new double[]
    ,并且更喜欢
    std::make_unique()
    以避免这种不匹配。@我的:根据问题的OP规范,这可能完全是浪费资源,这是不清楚的。@Jarod42:
    std::make_unique()
    不在C++11中,它是在C++14中添加的。@Mine在不同的容器之间共享的?在我的例子中,p_数据存储在一个映射中,其中值是地址,所以我猜在我的例子中,它的所有权是唯一的。也许您可以给出一些具体的例子?在这种情况下,vector存储共享的_ptr,所以在这里,即使我们可以交换指针(内存),std::list也不会有太大的好处?
    // my data container
    typedef std::unique_ptr<double[]> my_type;
    // or: using my_type = std::unique_ptr<double[]>;
    
    std::vector<my_type> my_storage;
    
    my_type ptr(new double[some_length]);
    my_storage.push_back(std::move(ptr));
    // or: my_storage.push_back(my_type(new double[some_length]));
    // or: my_storage.emplace_back(new double[some_length]);