2010-10-24 6 views
5

Comment le vecteur STL est-il généralement implémenté? Il a un stockage brut de char [] qu'il redimensionne occasionnellement par un certain facteur et appelle alors le placement nouveau quand un élément est push_back (une forme grammaticale très intéressante je devrais noter - les linguistes devraient étudier des formes verbales comme push_back :)
Et puis il y a les exigences d'alignement. Donc, une question naturelle se pose comment puis-je appeler un placement nouveau sur un char [] et assurez-vous que les exigences d'alignement sont satisfaites. Donc, je cherchai la norme C de 2003 pour le mot "alignement" et trouvé ces:Alignement des tableaux char

Paragraphe 3.9 Article 5

types d'objets ont des exigences d'alignement (3.9.1, 3.9.2). L'alignement d'un type d'objet complet est une valeur entière définie par l'implémentation représentant un nombre d'octets; un objet est affecté à une adresse qui répond aux exigences d'alignement de son type d'objet.

Paragraphe 5.3.4 Article 10:

Une nouvelle expression passe la quantité d'espace requis à la fonction d'allocation comme premier argument de type std :: size_t. Cet argument ne doit pas être inférieur à la taille de l'objet en cours de création; il peut être supérieur à la taille de l'objet créé uniquement si l'objet est un tableau. Pour les tableaux de char et unsigned char, la différence entre le résultat de la nouvelle expression et l'adresse retournée par la fonction d'allocation doit être un multiple entier de l'exigence d'alignement la plus stricte (3.9) de tout type d'objet dont la taille n'est pas supérieure à la taille du tableau en cours de création. [Note: Comme les fonctions d'allocation sont supposées renvoyer des pointeurs vers le stockage aligné pour les objets de n'importe quel type, cette contrainte sur l'allocation de l'allocation de tableau permet d'attribuer des tableaux de caractères. ]

Ces deux donnent une réponse parfaitement satisfaisante pour ma question ci-dessus, mais ...

Statement1:
Une exigence d'alignement pour un objet de type X où sizeof (X) == n est au moins l'exigence que l'adresse de X soit divisible par n ou quelque chose comme ça (mettre toutes les choses dépendantes de l'architecture dans le "ou quelque chose comme ça").

Question1: S'il vous plaît confirmer, affiner, ou infirmer l'instruction1 ci-dessus. Statement2: Si statement1 est correct, alors de la deuxième citation dans la norme il s'ensuit qu'un tableau de 5000000 caractères est alloué à une adresse divisible par 5000000 ce qui est complètement inutile si j'ai juste besoin du tableau de char en tant que tel, pas comme un stockage brut pour le placement possible d'autres objets.

Question2: Ainsi, sont les chances de succès allouer 1000 CHARS vraiment inférieur à 500 courts métrages (à condition courte est de 2 octets)? Est-ce pratiquement un problème?

Répondre

3

Une condition d'alignement d'un objet de type X où sizeof (X) == n est au moins l'exigence selon laquelle l'adresse de X soit divisible par n ou quelque chose comme que

L'exigence d'alignement d'un type est toujours un facteur de sa taille, mais n'a pas besoin d'être égale à sa taille. Il est généralement égal à la plus grande des exigences d'alignement de tous les membres d'une classe.

Un tableau de 5M char, pour son propre compte, doit seulement avoir une exigence d'alignement de 1, la même que l'exigence d'alignement d'un seul char. Ainsi, le texte que vous citez à propos de l'alignement de la mémoire allouée via l'opérateur global new (et malloc a une exigence similaire, bien qu'IIRC ne soit pas identique) signifie qu'une grande allocation doit obéir à l'exigence d'alignement la plus stricte de tous les types dans le système. En plus de cela, les implémentations excluent souvent de grands types de SIMD et exigent que la mémoire pour SIMD soit spécialement allouée. C'est un peu douteux, mais je pense qu'ils le justifient par le fait que les types d'extension non standard peuvent imposer des exigences spéciales arbitraires.

Ainsi, en pratique, le nombre que vous pensez est 5000000 est souvent 4 :-)

1

Q1: L'alignement n'est pas lié à la taille.

Q2: Théoriquement oui, mais vous trouverez difficilement une architecture qui a un type avec un tel alignement. SSE nécessite un alignement de 16 octets (le plus grand que j'ai vu).

+0

@Let_Me_Be: La raison pour laquelle je supposé l'alignement ** ** est liée à la taille est que si je prends un tableau de X et ils doivent tous obéir aux exigences d'alignement, puis les adresses a, a + sizeof (X), a + 2 * sizeof (X) ... etc. doivent toutes être conformes à ces exigences. Ce qui m'a conduit à définir la déclaration. Ai-je tort? –

+0

@Armen: Vous l'avez à l'envers. La taille de l'objet doit être un multiple de son alignement. Un «char» a généralement l'alignement 1, et un «int» doit généralement être aligné sur une limite de 4 octets. Une 'struct' contenant les deux reçoit l'alignement de son membre le plus strictement aligné (donc si elle contient un' char' et un 'int', alors la structure dans son ensemble requiert le même alignement qu'un' int'). L'objet doit alors aussi avoir une taille qui est un multiple d'un int. La même chose est vraie pour votre énorme tableau de caractères. Il ne contient que des caractères, et chaque caractère peut être placé à n'importe quel octet (n'importe quelle adresse divisible par 1) – jalf

+0

donc le tableau dans son ensemble a la même exigence d'alignement (et doit aussi être un multiple de 1, ce qui n'est pas difficile pour atteindre.;)) – jalf

4

Lorsque vous allouez dynamiquement de la mémoire à l'aide operator new, vous avez la garantie que:

Le pointeur retourné doit être convenablement aligné de manière à pouvoir être converti en un pointeur de tout type d'objet complet, puis utilisé pour accéder l'objet ou le tableau dans le stockage alloué (jusqu'à ce que le stockage soit explicitement désalloué par un appel à une fonction de désallocation correspondante) (C++ 03 3.7.3.1/2).

vector ne crée pas de tableau de char; il utilise un allocateur. L'allocateur par défaut utilise ::operator new pour allouer de la mémoire.