I must have been tired or something yesterday, the thing about auto_ptr's is that they do not apply for arrays - like char arrays, because of the difference between delete and delete[] (auto_ptr uses the former). Your example could have been rewritten if you use an object that encapsulates the array... but then you basically created a string anyway.
auto_ptr's are great because of how c++ guarantees that destructors get called. on ~auto_ptr(), it frees it's element; therefore it's pretty much impossible to create memoryleaks when using auto_ptr's. also, they're syntatically identical to standard pointers because of operator overloading. below is an example that illustrates it:
#include <memory>
#include <iostream>
// our data struct. tells us when it exists
struct mystruct {
int x, y;
mystruct() {
std::cout << this << ": constructedn";
}
~mystruct() {
std::cout << this << ": destructedn";
}
};
//typedefs so you dont have to write std::auto_ptr all over the place
typedef std::auto_ptr<mystruct> data_ptr;
typedef mystruct * raw_data_ptr;
//returns an auto_ptr
data_ptr data_creater() {
data_ptr ret(new mystruct);
ret->x = 3;
ret->y = 5;
return ret;
}
//returns a raw pointer
raw_data_ptr data_creater_raw() {
raw_data_ptr ret(new mystruct);
ret->x = 3;
ret->y = 5;
return ret;
}
//this evil class throws exceptions
class some_class
{
public: void do_something() { throw 1; }
};
void exampleone() {
//get data pointer
raw_data_ptr my_data = data_creater_raw();
//do some work here
some_class my_class;
my_class.do_something();
//done with work, now we remember (or forget) to free pointer!
delete my_data;
// except we of course never reach this point because some_class::do_something() threw an exception.
// we have now created a memory leak, even though we wrote the code for deletion!
}
void exampletwo() {
//my_data, a templated auto_ptr, now owns the pointer returned.
//when auto_ptr goes out of scope, it frees it's pointer.
data_ptr my_data = data_creater();
some_class my_class;
//the simulated exception here is not a problem: c++ ensures destructors
//are called on exceptions.
my_class.do_something();
}
data_ptr examplethree() {
//my_data, a templated auto_ptr, now owns the pointer returned.
data_ptr my_data = data_creater();
//we now return the pointer - on copying the auto_ptr loses ownership
// - and even if it doesn't get captured, it will still be released!
return my_data;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "Example onen";
try {
exampleone();
}
catch(...) {}
std::cout << "Example twon";
try {
exampletwo();
}
catch(...) {}
std::cout << "Example three:n";
examplethree();
system("pause");
return 0;
}boost or the new unique_ptr in c++0x11 will however allow to rewrite your example your by substituting char * with unique_ptr<char[]> (more or less)