Reputation: 387
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
Reputation: 171097
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