The rule of thumb is that if you need to _use_ a class defind in the
header <header>, then you need to include <header>. Simple as that.
The rule of thumb is that if you refer to a class or a typedef
(std::string is the latter), then there must be a declaration
visible at that point. The only legal way to get a declaration
for std::string is to include <string>. Any reference to
std::string, in any way, shape, form or fashion, without having
So, if you define any object of type 'std::string', you need
to do the #include, according to my rule. If you need to
declare an object of type pointer to, or reference to,
'std::string', you don't really need to include <string>, but
you better since 'std::string' is a typedef and you shouldn't
really forward-declare what is a typedef (although you could
do it with a simple class, for example).
And even if std::string were a simple class, how would you
forward declare it, given that you're not allowed to declare
symbols in std. (I don't know if an implementation is allowed
to add additional template arguments---with default values---or
not. The standard doesn't seem to say. But of course, if an
implementation has this liberty, then you can't possibly forward
declare it, because you don't know what the actual forward
declaration should look like.)