Dupliquer possible:
Puis-je obtenir une chaîne C non-const à partir d’une chaîne C ++?
Dois-je d’abord le convertir? J’ai vu dans un autre post que .c_str () peut être utilisé si la fonction attend const char *. Qu’en est-il pour juste char *?
std::vector buffer(s.begin(), s.end()); foo(&buffer[0], buffer.size()); s.assign(buffer.begin(), buffer.end());
Il n’existe aucun moyen d’obtenir un caractère * d’une chaîne dont le fonctionnement sur toutes les plates-formes est garanti, pour la simple raison que la ssortingng
n’est pas obligée d’utiliser un stockage contigu.
Votre ligne de conduite la plus sûre et la plus portable consiste à copier la chaîne quelque part qui utilise un stockage contigu (un vector
peut vector
être) et à l’utiliser à la place.
vector chars(my_ssortingng.begin(), my_ssortingng.end()); char* ptr = &chars[0];
Si vous voulez être hacky, non-portable et résolument dangereux, vous pouvez vérifier que votre implémentation de ssortingng
utilise effectivement un stockage contigu, puis peut-être utiliser ceci:
&my_str[0]
Mais je donnerais un coup de poing à tout développeur qui travaillerait pour moi et qui aurait fait cela.
J’ai appris qu’il n’existe actuellement aucune implémentation STL connue qui ne stocke pas les données de chaîne dans un tableau contigu, ce qui rendrait &my_str[0]
sûr. Il est également vrai (et on m’a demandé de le préciser) que, dans le prochain standard C ++ 0x, il sera nécessaire que le stockage soit contigu.
Il a été suggéré que parce que si ces faits que mon post est factuellement incorrect.
Décide toi-même, mais je dis non. Ce n’est pas dans la norme C ++ actuelle, et donc ce n’est pas obligatoire. Dans la pratique, je continuerai de faire les choses comme je l’ai suggéré et, lors de toute révision de code, je signalerai tout code supposant que le stockage sous-jacent est contigu.
Considère ceci. Supposons qu’il y ait une question sur les pointeurs vtable. Quelqu’un veut examiner une classe et obtenir le pointeur sur une fonction virtuelle en regardant la table virtuelle. Je leur dirais immédiatement de ne pas le faire car il n’est pas fait mention de la manière dont les méthodes virtuelles sont implémentées en C ++. Chaque implémentation que je connais utilise vtables, et je ne peux pas penser à un meilleur moyen de le faire. Il est probable que le polymorphism sera implémenté pour toujours à l’aide de vtables. Est-ce que cela permet d’examiner directement le vtable?
OMI non, car cela dépend de détails d’implémentation non documentés. Vous n’avez aucun contrôle sur cela et cela pourrait changer à tout moment. Même si vous vous attendez à ce que cela ne change jamais, il est toujours une mauvaise ingénierie de s’appuyer sur ces détails d’implémentation.
Décider vous-même.
Il y a trois scénarios:
Ensuite, copiez la chaîne dans un tampon temporaire et transmettez-la à la fonction, comme suit:
void callFoo(std::ssortingng& str); { char* tmp = new char str(str.length() +1); strncpy(tmp, str.c_str(), str.length()); foo(tmp); // Include the following line if you want the modified value: str = tmp; delete [] tmp; }
Ensuite, vous pouvez chasser le const
et le transmettre à la fonction
void callFoo(const std::ssortingng& str) { foo(const_cast str.c_str()); }
Dans ce cas, changez la fonction pour accepter soit une ssortingng&
(si elle modifie le tampon d’entrée), soit const char*
ou une const ssortingng&
si ce n’est pas le cas.
Lorsqu’un paramètre est déclaré comme char *, il est implicitement supposé que la fonction aura pour effet secondaire la modification de la chaîne pointée. En raison de cela et du fait que c_str () n’autorise pas les modifications de la chaîne incluse, vous ne pouvez pas explicitement transmettre un std :: ssortingng à une telle méthode.
Quelque chose comme ceci peut être réalisé en suivant l’approche suivante:
#include #include #include void modify_ssortingng(char* pz) { pz[0] = 'm'; } class ssortingng_wrapper { std::ssortingng& _s; char* _psz; ssortingng_wrapper(const ssortingng_wrapper&); ssortingng_wrapper& operator=(const ssortingng_wrapper&); public: ssortingng_wrapper(std::ssortingng& s) : _s(s), _psz(0) {} virtual ~ssortingng_wrapper() { if(0 != _psz) { _s = _psz; delete[] _psz; } } operator char*() { _psz = new char[_s.length()+1]; strcpy(_psz,_s.c_str()); return _psz; } }; int main(int argc, char** argv) { using namespace std; std::ssortingng s("This is a test"); cout << s << endl; modify_string(string_wrapper(s)); cout << s << endl; return 0; }
Si vous êtes certain que le caractère * ne sera pas modifié, vous pouvez utiliser const_cast pour supprimer const.
C’est une solution sale mais je suppose que cela fonctionne
std::ssortingng foo("example");
char* cpy = (char*)malloc(foo.size()+1);
memcpy(cpy, foo.c_str(), foo.size()+1);