drkg4b
drkg4b

Reputation: 387

Assign pair of raw pointers returned by a function to unique_ptr

I've looked around a little bit but couldn't find an answer to this.

I have a function returning a pair of pointers to objects, the situation can be simplified to:

#include <iostream>
#include <utility>
#include <memory>

std::pair<int *, int *> shallow_copy()
{

   int *i = new int;
   int *j = new int;

   *i = 5;
   *j = 7;

   return std::make_pair(i, j);
}

int main(int argc, char *argv[])
{
   std::pair<int *, int *> my_pair = shallow_copy();

   std::cout << "a = " << my_pair.first << " b = " << *my_pair.second << std::endl;

   // This is just creating a newpointer:
   std::unique_ptr<int> up(my_pair.first);

   std::cout << "a = " << &up << std::endl;

   delete my_pair.first;
   delete my_pair.second;

   return 0;
}

I cannot change the return value of the function. From std::cout << "a = " << &up << std::endl; I can see that the address of the smart pointer is different from the address of the raw pointer.

Is there a way to capture tha std::pair returned by the function in a std::unique_ptr and prevent memory leaks without calling delete explicitly?

NB: The question have been edited to better state the problem and make me look smarter!

Upvotes: 0

Views: 485

Answers (1)

You're doing it the right way, but testing it the wrong one. You're comparing the address in first with the address of up. If you print up.get() instead (the address stored in up), you'll find they're equal.

In addition, your code has a double-delete problem. You do delete my_pair.first;, which deallocates the memory block pointed to by my_pair.first and also by up. Then, the destructor of up will deallocate it again when up goes out of scope, resulting in a double delete.

You also asked how to capture both pointers in smart pointers. Since the constructor of std::unique_ptr taking a raw pointer is explicit, you cannot directly do this with a simple std::pair<std::unique_ptr<int>, std::unique_ptr<int>>. You can use a helper function, though:

std::pair<std::unique_ptr<int>, std::unique_ptr<int>> wrapped_shallow_copy()
{
  auto orig = shallow_copy();
  std::pair<std::unique_ptr<int>, std::unique_ptr<int>> result;
  result.first.reset(orig.first);
  result.second.reset(orig.second);
  return result;
}

Now, use wrapped_shallow_copy() instead of shallow_copy() and you will never leak memory from the call.

Upvotes: 2

Related Questions