3 votes

std::string politique d'allocation

Je suis un peu perdu avec certaines des implémentations de base des chaînes de caractères. J'ai parcouru les sources pour comprendre le fonctionnement interne et apprendre de nouvelles choses. Je n'arrive pas à comprendre entièrement comment la mémoire est gérée.

Quelques informations sur l'implémentation de base des chaînes de caractères.

  • L'allocateur brut est pour le type char

    typedef typename _Alloc::template rebind<char>::other _Raw_bytes_alloc;
  • ...puis lors de l'allocation, Rep est placé dans le tampon alloué __size est calculé pour correspondre également aux caractères

    size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
    void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
    _Rep *__p = new (__place) _Rep;
  • Voici comment les données de caractères sont extraites du tampon _Rep.

    _CharT* _M_refdata() throw()
    {
        return reinterpret_cast<_CharT*>(this + 1);
    }
  • Mise en place du personnage - pour un type de voie

    _M_assign(__p->_M_refdata(), __n, __c);

Ce qui me dérange, c'est que l'allocateur brut est de type char, mais que la mémoire allouée peut contenir un objet _Rep, plus les données du caractère (qui ne doivent pas nécessairement être de type char).

Par ailleurs, pourquoi (ou plutôt comment) l'appel à la fonction _M_refdata savoir où se trouve le début (ou la fin) des données du caractère dans la mémoire tampon (c'est à dire this+1 )

Edit : fait this+1 il suffit de pousser le pointeur interne à la position suivante après le _Rep objet ?

J'ai une connaissance de base de l'alignement et du moulage de la mémoire, mais cela semble aller au-delà de tout ce que j'ai lu.

Quelqu'un peut-il m'aider ou m'indiquer des lectures plus informatives ?

5voto

filmor Points 7439

Tu manques le nouveau placement. La ligne

_Rep *__p = new (__place) _Rep;

initialise un nouveau _Rep -objet à __place . L'espace pour cela a déjà été alloué auparavant (ce qui signifie qu'un placement-nouveau n'alloue pas par lui-même, c'est en fait seulement un appel au constructeur).

L'arithmétique des pointeurs en C et C++ vous indique que this + 1 est un pointeur qui désigne sizeof(*this) octets à droite de this . Étant donné qu'il a été attribué (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep) octets avant, l'espace après le _Rep est utilisé pour les données de caractères. La disposition est donc la suivante :

| _Rep |  (__capacity + 1) * _CharT  |

0voto

Zan Lynx Points 23100

Allocateurs, comme les C malloc retournent des pointeurs sur des octets, pas des objets. Ainsi, le type de retour est soit char * o void * .

Quelque part dans les normes C et C++, il y a une clause qui permet explicitement de réinterpréter les castings entre char et tout autre type d'objet. En effet, le C a souvent besoin de traiter les objets comme des tableaux d'octets (comme lors de l'écriture sur le disque ou sur une prise réseau) et il doit traiter les tableaux d'octets comme des objets (comme lors de l'allocation d'une plage de mémoire ou de la lecture du disque).

Pour se protéger contre les problèmes d'aliasing et d'optimisation, vous êtes no autorisé à lancer le même char * à différents types d'objets et une fois que vous avez lancé un char * à un type d'objet, vous n'êtes pas autorisé à modifier la valeur de l'objet en écrivant dans les octets.

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