const char* foo("1234");
if( ss >> i )
std::cout << "i is: " << i ;
std::cout << "error";
The reason for using stringstreams is that your conversion will fail if the string contains anything which can't be converted to an int - which, if you're dealing with user input, is a real problem. if you use a stringstream, you can detect the error, without it messing up the rest of the program.
I suppose I should add that atoi() has no reliable way of handling any errors that might be thrown up when your conversion fails. This is where stringstreams provide a far more robust solution, that you can test for failure before using the retrieved value.