简体   繁体   中英

Best strategy for manual memory management using smart pointers?

Is there a recommended strategy for dealing with external libraries which expect manually managed raw pointers. For example a method which takes a vector of pointers:

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

so generally you'd create your vector with something like:

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();

I'd much prefer to use smart pointers but the library will not take them. This leaves me wondering if something like this is more stinky than just doing it manually:

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();

The second version seems safer in case of exceptions or mistakes but it does risk dangling pointers. Am i missing something obvious here? What do/would you do?

You can declare a small class which will own the vector of raw pointers, and delete the pointers in the destructor:

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

you should be able to reuse the class in all places where you use the library.

You can use 'scope exit' idiom :

//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 

EDIT:
I'm sorry, but Wojtek Surowka's answer is not exception safe or required extra try catch block in constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM