32 votes

Est-il raisonnable d'utiliser std :: basic_string <t> comme tampon contigu lors du ciblage de C ++ 03?

Je sais qu'en C++03, techniquement, l' std::basic_string modèle n'est pas nécessaire d'avoir de la mémoire contiguë. Cependant, je suis curieux de voir comment de nombreuses implémentations existent pour les compilateurs modernes que réellement profiter de cette liberté. Par exemple, si on veut utiliser basic_string de recevoir les résultats de certaines API C (comme dans l'exemple ci-dessous), il semble idiot d'allouer un vecteur juste pour le transformer en une chaîne de caractères immédiatement.

Exemple:

DWORD valueLength = 0;
DWORD type;
LONG errorCheck = RegQueryValueExW(
        hWin32,
        value.c_str(),
        NULL,
        &type,
        NULL,
        &valueLength);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);
else if (valueLength == 0)
    return std::wstring();

std::wstring buffer;
do
{
    buffer.resize(valueLength/sizeof(wchar_t));
    errorCheck = RegQueryValueExW(
            hWin32,
            value.c_str(),
            NULL,
            &type,
            &buffer[0],
            &valueLength);
} while (errorCheck == ERROR_MORE_DATA);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);

return buffer;

Je sais que ce type de code peut légèrement réduire la portabilité, car elle implique que l' std::wstring est contiguë, mais je me demandais juste comment portables qui fait de ce code. Autrement dit, comment peut compilateurs fait profiter de sa liberté d'avoir non contigus de la mémoire?


EDIT: j'ai mis à jour cette question de parler de C++03. Les lecteurs sont priés de noter que lors du ciblage de C++11, la norme exige maintenant que basic_string être contiguës, de sorte que la question ci-dessus est un non-problème lors du ciblage de cette norme.

25voto

Jerry Coffin Points 237758

Je considère qu'il est assez sûr de supposer que std::string alloue son espace de stockage de manière contiguë.

À l'heure actuelle, tous connus des implémentations std::string allouer un espace contigu.

En outre, le projet de C++ 0x (N3000) [Edit: Attention, lien direct vers le fichier PDF] exige que l'espace alloué contigu (§21.4.1/5):

Le char comme des objets dans un basic_string objet doit être stocké de manière contiguë. C'est, pour tout basic_string objet, l'identité &*(s).begin() + n) == &*s.begin() + n tient pour toutes les valeurs de n telles que 0 <= n < s.taille().

En tant que tel, les chances d'un actuel ou futur de la mise en œuvre de l' std::string non contigus de stockage sont quasiment nuls.

14voto

Michael Burr Points 181287

Un temps, il y avait une question sur la possibilité d'écrire à la capacité de stockage pour un std::string comme si c'était un tableau de caractères, et il dépendait de savoir si le contenu d'un std::string étaient contigus:

Ma réponse a indiqué que, conformément à un couple bien considéré sources (Herb Sutter et Matt Austern) le cours du C++ standard ne nécessitent std::string pour stocker ses données contiguës, sous certaines conditions (une fois que vous vous appelez str[0] en supposant str est std::string) et que de ce fait assez bien les forces de la part de toute mise en œuvre.

En gros, si vous combinez les promesses faites par l' string::data() et string::operator[]() - on en conclure qu' &str[0] doit renvoyer une mémoire tampon contiguë. Donc Austern suggère que le comité a juste rendre explicite, et apparemment c'est ce qui va arriver dans le 0x standard (ou sont-ils en l'appelant à la norme 1x maintenant?).

Donc, à strictement parler d'une mise en œuvre n'a pas à mettre en oeuvre std::string à l'aide de stockage contigu, mais il a à faire à peu près sur demande. Et votre exemple de code n'est juste qu'en passant en &buffer[0].

Liens:

0voto

Potatoswatter Points 70305

Edit: Vous voulez l'appeler en &buffer[0], pas buffer.data()car [] renvoie un non-const de référence et de ne notifier à l'objet que son contenu peut changer de façon inattendue.


Il serait plus propre de le faire buffer.data(), mais vous devriez vous inquiéter moins sur contigu de mémoire que la mémoire partagée entre les structures. string des implémentations peuvent s'attendre à être prévenu quand un objet est en cours de modification. string::data exige en particulier que le programme n'est pas de modifier la mémoire tampon interne retourné.

De TRÈS fortes chances que certains de la mise en œuvre permettra de créer un tampon pour toutes les chaînes non initialisée en plus d'avoir une longueur de 10 ou quoi que ce soit.

Utiliser un vector ou même un tableau avec new[]/delete[]. Si vraiment vous ne pouvez pas copier le tampon, légalement initialiser la chaîne à quelque chose d'unique avant de le changer.

-1voto

pm100 Points 8303

Le résultat n'est pas défini et je ne le ferais pas. Le coût de la lecture dans un vecteur et de sa conversion en chaîne est trivial dans les tas c ++ modernes. VS le risque que votre code meure dans Windows 9

aussi, cela n'a-t-il pas besoin d'un const_cast sur & buffer [0]?

-2voto

leon Points 80

Bien sûr, allouer un vecteur ici est idiot. L'utilisation de std :: wstring ici n'est pas non plus judicieuse. Il est préférable d'utiliser un tableau de caractères pour appeler le winapi. construire un wstring lors du retour de la valeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X