The best approach is that the function that allocates or creates an object also destroys it. In the example you gave, there are two possible solutions:
void MyNumber(int* pMyNumber) {
if (pMyNumber != 0)
*pMyNumber = 13;
}
int main() {
int* pMyNumber = new int;
MyNumber(pMyNumber);
std::cout << "My favourite number is: " << *pMyNumber << std::endl;
delete pMyNumber;
return 0;
}
This solution delegates the allocation and freeing of the variable to the calling program. The created object is then passed to the function that sets its vale.
int* CreateMyNumber() {
int * pMyNumber = new int;
*pMyNumber = 13;
return pMyNumber;
}
void DestroyMyNumber(int* pMyNumber) {
delete pMyNumber;
}
int main() {
int* pMyNumber = CreateMyNumber();
std::cout << "My favourite number is: " << *pMyNumber << std::endl;
DestroyMyNumber(pMyNumber);
return 0;
}
This solution provides a pair of function that respectively create and destroy something. The calling function is still responsible for calling the Destroy function to destruct the object that the Create function constructed.
This is a more generic solution that allows the designer of the Create and Destroy functions to use other allocators than new and delete, or maybe even have Create return a pointer to a static object that doesn't need to be destroyed. (so the Destroy function would do nothing)