Mesmo sabendo que você viu que eles fazem o mesmo, ou que .data () chama .c_str (), não é correto assumir que esse será o caso para outros compiladores. Também é possível que seu compilador mude com uma versão futura.
2 razões para usar std :: string:
std :: string pode ser usado para texto e dados binários arbitrários.
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
Você deve usar o método .c_str () quando estiver usando sua string como exemplo 1.
Você deve usar o método .data () quando estiver usando sua string como exemplo 2. Não porque seja perigoso usar .c_str () nesses casos, mas porque é mais explícito que você está trabalhando com dados binários para outros revisarem seu código.
Possível armadilha com o uso de .data ()
O código a seguir está errado e pode causar um segfault em seu programa:
std::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()
Por que é comum que os implementadores façam .data () e .c_str () fazerem a mesma coisa?
Porque é mais eficiente fazer isso. A única maneira de fazer .data () retornar algo que não seja terminado em nulo, seria ter .c_str () ou .data () copiar seu buffer interno, ou usar apenas 2 buffers. Ter um único buffer terminado em null sempre significa que você sempre pode usar apenas um buffer interno ao implementar std :: string.
.data()
, portanto, eles não são mais equivalentes para strings não constantes.