Além das razões postadas aqui, há também outra - a compatibilidade binária . Os escritores das bibliotecas não têm controle sobre qual std::stringimplementação você está usando e se ela possui o mesmo layout de memória que o deles.
std::stringé um modelo, portanto, sua implementação é obtida nos cabeçalhos STL locais. Agora imagine que você está usando localmente alguma versão STL com desempenho otimizado, totalmente compatível com o padrão. Por exemplo, você pode optar por invadir o buffer estático em cada um std::stringpara reduzir o número de alocações dinâmicas e falhas de cache. Como resultado, o layout da memória e / ou o tamanho da sua implementação são diferentes dos da biblioteca.
Se apenas o layout for diferente, algumas std::stringfunções de membro chamam instâncias transmitidas da biblioteca para o cliente ou o contrário pode falhar, dependendo de quais membros foram deslocados.
Se o tamanho também for diferente, todos os tipos de bibliotecas que possuem std::stringmembros parecerão ter diferentes sizeof quando marcados na biblioteca e no código do cliente. Os membros de dados após o std::stringmembro também terão os deslocamentos deslocados, e qualquer acesso direto / acessador em linha chamado do cliente retornará lixo, apesar de "parecer bem" ao depurar a própria biblioteca.
Bottomline - se a biblioteca e o código do cliente forem compilados em std::stringversões diferentes , eles serão vinculados muito bem, mas isso pode resultar em alguns erros desagradáveis e difíceis de entender. Se você alterar sua std::stringimplementação, todas as bibliotecas que expõem membros do STL deverão ser recompiladas para corresponder ao std::stringlayout do cliente . E como os programadores desejam que suas bibliotecas sejam robustas, você raramente será std::stringexposto em qualquer lugar.
Para ser justo, isso se aplica a todos os tipos de STL. IIRC eles não têm layout de memória padronizado.