使用智能指针进行手动内存管理的最佳策略?

时间:2014-07-29 14:03:20

标签: c++ c++11

是否有推荐的策略来处理期望手动管理原始指针的外部库。例如,一个采用指针向量的方法:

ALibraryFunc(std::vector<ALibraryData*> p);

所以通常你会用以下内容创建你的矢量:

std::vector<ALibraryData*> myVec;
for(...)
{
    myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
//and then
for(auto &a:myVec)
{
    delete a;
}
myVec.clear();

我更喜欢使用智能指针,但图书馆不会接受它们。这让我想知道这样的事情是否比手动做得更臭:

std::vector<std::unique_ptr<ALibraryData>> myVecUP;
std::vector<ALibraryData*> myVec;
for(...)
{
    myVecUP.push_back(std::make_unique<ALibraryData>(args));
    myVec.push_back(myVecUP.back().get());
}
//and then
ret = ALibraryFunc(myVec);
myVec.clear();
myVecUP.clear();

第二个版本在异常或错误的情况下似乎更安全,但它确实存在悬挂指针的风险。我错过了一些明显的东西吗?你会做什么/你会做什么?

2 个答案:

答案 0 :(得分:5)

你可以声明一个拥有原始指针向量的小类,并删除析构函数中的指针:

struct VecOwner {
 std::vector<ALibraryData*> vec;
 VecOwner(<some arguments>)
 {
     // fill the vector here
 }
 ~VecOwner()  
 {
   for(auto &a:vec)
     delete a;
   vec.clear();
 }
};

您应该能够在使用该库的所有地方重用该类。

答案 1 :(得分:3)

您可以使用&#39;范围退出&#39;成语:

//open scope block
{
    std::vector<ALibraryData*> myVec;
    ////////////////////////////////////////
    struct MyVecRAIICleaner{ 
      std::vector<ALibraryData*> * myVecPtr;
      ~MyVecRAIICleaner(){ 
        if (myVecPtr) {
         for(auto& a: *myVecPtr)
            delete a;
         myVecPtr->clear();
        }
       }
    } myRAIICleaner = {&myVec};
    ////////////////////////////////////////
   for(...)
   {
       myVec.push_back(new ALibraryData(args));
    }
    //and then
    ret = ALibraryFunc(myVec);

    /** You needn't below code. */
    ////and then 
    //for(auto &a:myVec)
    //{
    //    delete a;
    //}
    //myVec.clear();

}// end scope block 

编辑:
对不起,但是Wojtek Surowka的答案不是例外安全或者在构造函数中需要额外的try catch块。