Même si vous avez vu qu'ils font la même chose, ou que .data() appelle .c_str(), il n'est pas correct de supposer que ce sera le cas pour d'autres compilateurs. Il est également possible que votre compilateur change avec une future version.
2 raisons d'utiliser std::string :
std::string peut être utilisé à la fois pour du texte et des données binaires arbitraires.
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
Vous devez utiliser la méthode .c_str() lorsque vous utilisez votre chaîne comme dans l'exemple 1.
Vous devez utiliser la méthode .data() lorsque vous utilisez votre chaîne de caractères comme dans l'exemple 2. Non pas parce qu'il est dangereux d'utiliser .c_str() dans ces cas, mais parce qu'il est plus explicite que vous travaillez avec des données binaires pour les autres personnes qui examinent votre code.
Piège possible avec l'utilisation de .data()
Le code suivant est erroné et pourrait provoquer un défaut de fonctionnement dans votre programme :
std::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()
Pourquoi est-il courant que les implémenteurs fassent faire la même chose à .data() et .c_str() ?
Parce qu'il est plus efficace de le faire. La seule façon de faire en sorte que .data() renvoie quelque chose qui ne soit pas à terminaison nulle, serait de faire en sorte que .c_str() ou .data() copient leur tampon interne, ou d'utiliser simplement 2 tampons. Avoir un seul tampon à terminaison nulle signifie que vous pouvez toujours utiliser un seul tampon interne lorsque vous implémentez std::string.