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)