Question

J'ai vu une classe qui est une classe qui est définie comme ceci ..

class StringChild : public StringBase
    {
public:
    //some non-virtual functions
    static StringChild* CreateMe(int size);
private:
    unsigned char iBuf[1];
    };

La fonction d'usine statique a l'implémentation suivante.

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

Donc, autant que je sache, cette fonction utilise le placement nouveau pour étendre cette classe.

Est-ce sûr uniquement parce qu'il n'y a qu'un seul membre et qu'il est alloué sur le tas?

Était-ce utile?

La solution

C’est un vieux truc en C qui servait à contourner la non-disponibilité des tableaux de longueur variable en clair C. Oui, cela fonctionne aussi en C ++ tant que vous utilisez des constructions allocateur appropriées (comme l’allocation d’un tas de mémoire brute). taille désirée puis placement nouvel objet). C'est sûr tant que vous ne vous baladez pas à la fin de la mémoire allouée, mais cela a tendance à confondre au moins certains débogueurs de mémoire.

Lorsque vous utilisez cette technique, vous devez être absolument certain que le tableau de longueur variable est le dernier élément de la présentation de l'objet. Sinon, vous passerez au-dessus des autres variables internes.

Je suis toutefois un peu dubitatif quant à la mise en œuvre de la fonction factory. Je suppose que le paramètre 'size' correspond en fait à la taille de tableau souhaitée? De plus, n'oubliez pas que vous devez libérer la mémoire ci-dessus en utilisant "free" et non "delete", même si cette dernière peut fonctionner dans la plupart des cas.

À moins d'une raison convaincante pour laquelle la mémoire doit être gérée de cette façon, je remplacerais simplement le tableau par un std :: vector.

Autres conseils

Cela devrait convenir aux POD, à condition que iBuf soit le dernier membre de la structure. Les problèmes avec les non-POD pourraient être que par exemple. le compilateur est libre de réorganiser les membres publics / privés / protégés, les classes de base virtuelles finissent à la fin de l’objet le plus dérivé IIUC, etc.

Votre structure est non-POD (elle a une classe de base), donc je ne le recommanderais pas.

De même, si vous créez des instances comme celle-ci

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

Vous devez vous assurer que la mémoire acquise par malloc doit être libérée avec free. Supprimez donc vos instances de la manière suivante:

obj->~StringChild();
free(obj);

Peut-être aimeriez-vous utiliser :: operator new () pour l'allocation

À proprement parler, puisque StringChild est dérivé de StringBase , il n'est pas sécurisé. La norme C ++ ne spécifie pas la mise en page pour les sous-objets de la classe de base. Article 10, paragraphe 3:

  

L'ordre dans lequel les sous-objets de la classe de base sont alloués dans l'objet le plus dérivé (1.8) n'est pas spécifié.

Si StringChild était une structure POD, une telle technique serait sans danger.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top