Comment est-ce que je passe un std :: ssortingng à une fonction qui attend char *?

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.

MODIFIER:

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:


Si la fonction est en dehors de votre contrôle et qu’elle modifie la chaîne, ou vous ne pouvez pas et ne pouvez pas savoir si elle modifie la chaîne:

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; } 

Si la fonction est en dehors de votre contrôle, mais que vous êtes certain qu’elle ne modifie pas la chaîne, et que ne pas prendre l’argument comme const est simplement une erreur de la part de l’API.

Ensuite, vous pouvez chasser le const et le transmettre à la fonction

 void callFoo(const std::ssortingng& str) { foo(const_cast str.c_str()); } 

Vous contrôlez la fonction (et il ne serait pas trop dérangeant de modifier la signature).

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);