Hello.My Problem is that if I new an object in a function, say to create a character string on the heap, how to delete it long after the function returns?
Functions returning a pointer to a dynamically allocated memory depend heavily on the code that call the function to do the proper clean-up after finish using it. What if after calling the function, the outside code forget to do a delete or free ?
There is no easy solution but Scott Meyers propose to have something called auto_ptr concept which is a class that "wrap" the pointer ? Then when that auto_ptr object is destructed say out of scope for e.g, inside the auto_ptr destructor it will delete and free the pointer dynamically allocated memory.
Somehow I find the whole auto_ptr concept an overkill. I will still go by the plain old simpler way of making it a discipline to free those functions that return me a pointer when I finish using it :)
#include <iostream>// for use of cin, cout
usingnamespace std;
char* NewString(char* pch)
{
// allocate for new string
int n = 1 + strlen(pch);
char* pchLocal = newchar[ n ];
strcpy_s(pchLocal, n*sizeof(char), pch);
return(pchLocal);
}
int main()
{
char* str1 = NewString("New string here!");
cout << str1 << endl;
delete str1;
system("PAUSE");// OK for "casual" use?
return 0;
}
This program seems to run fine and does not trigger any heap corruption or other errors. I think that the char* returned by NewString() is what Bazzy was referring to.
You seem to be misunderstanding scopes. The pointer goes out of scope, yes. But the dynamically allocated object doesn't. If you return a copy of the pointer (which is what a normal return-statement does), you can still use the object. Just remember to delete it, too.
That said, this way is possible and 100% legit, but it's not the nicest way to do this and most certainly not the most leak-free way.
Not leak-free? Is this because the programmer might forget to include line 19?
In response to sohguanh's post about using a class to "wrap" a pointer being used for dynamic memory allocation of a character array, how about this? The DAD class below automates use of its char* pwic data member so the programmer need not get his fingers dirty with "new" or "delete" while using it.
// A class for using dynamic character arrays
#include <iostream>
usingnamespace std;
class DAD
{
public:
char* pwic;// pointer to string in class
char* assignWord(char* pch);// return pointer to new string
DAD(char* pch = NULL);// overloaded. Pass a char* now or call copyWord() later
~DAD();// destructor
};
// will delete previous string and allocate for new
char* DAD::assignWord(char* pch)
{
if( pwic != NULL )// delete previously allocated array
{
delete [] pwic;
pwic = NULL;
}
// allocate for new string
int n = 1 + strlen(pch);
pwic = newchar[ n ];
strcpy_s(pwic, n*sizeof(char), pch);
cout << "pwic deleted + new again" << endl;
return(pwic);
}
// constructor - allocates char array and copies to it
DAD::DAD(char* pch )
{
if( pch != NULL )
{
int n = 1 + strlen(pch);
pwic = newchar[ n ];
strcpy_s(pwic, n*sizeof(char), pch);
cout << "DAD constructor here" << endl;
}
else
pwic = NULL;// no string supplied to constructor
}
// destructor - deletes char array
DAD::~DAD()
{
if( pwic != NULL )
delete [] pwic;
cout << "DAD destructor was here" << endl;
}
void ShowMessage(void)
{
DAD localString("Hello from local DAD");
cout << localString.pwic << endl;
localString.assignWord("How's the weather in main()?");
cout << localString.pwic << endl;
return;// ~DAD() called on localString here
}
int main()
{
ShowMessage();// I want call to ~DAD() to show so I'll use a local DAD
DAD mainDAD;// just checking that it's safe to call ~DAD() on an uninitialized DAD
system("PAUSE");
return 0;
}
In this case wouldn't you need to do this? After all you are dynamically allocating an array of characters.
delete [] str1;
Incidentally that is why you should avoid doing it this way. It is very error prone. fun2code's initial example is incorrect. It isn't so bad in a simple program but as you can see, even in a simple program mistakes can be made. The program might run fine but that doesn't mean that it is correct. A failure to use the correct form of delete results in undefined behavior so it is possible that in a more complex program that technique could result in the program crashing or exhibiting unexpected behavior.
There is no easy solution but Scott Meyers propose to have something called auto_ptr concept which is a class that "wrap" the pointer ? Then when that auto_ptr object is destructed say out of scope for e.g, inside the auto_ptr destructor it will delete and free the pointer dynamically allocated memory.
auto_ptr doesn't work for arrays. For dynamic arrays use std::string or one of the other sequence containers such as vector, deque, or list.
I'm not sure what fun2code's latest example was designed to show other than that a wrapper class makes it a little easier since the delete has to be done only in one or two places instead of by the caller. However if you write your own wrapper you still have to remember that and provide a convenient and useful interface. This is why we have std::string in the C++ STL.
That is all that my example was meant to show. Clearly, std::string is a superior tool. Sometimes I build things like the DAD class as an exercise, just to see if it will work.
That is all that my example was meant to show. Clearly, std::string is a superior tool. Sometimes I build things like the DAD class as an exercise, just to see if it will work.
Hi your DAD class could overload some operator to make it more intuitive to use maybe :) In the auto_ptr reference implementation, Scott Meyers also overload some operators so that when we have a variable like auto_ptr, we use it as though it is a pointer variable but we don't have to worry to delete or free etc issues.