J'ai été conseillé il y a un moment qui était un lieu commun à utiliser void foo (int n) {
std::vector<char> scoped_array (n);
char* pointer = &scoped_array[0];
file.read ( pointer , n );
for (int i = 0; i < n; ++i) {
//do something
}
}
6 Réponses :
Si vous souhaitez obtenir un comportement plus propre dans ce scénario, vous pouvez remplacer l'utilisation de Une solution pragmatique serait d'initier le vecteur avec N + 1 entrées et contraignez l'accès à 0..n-1 (comme ce code le fait déjà). P> A [0] code> avec l'utilisation
a.at (0) code>, qui va lancer si le L'index est invalide.
void foo (int n) {
std::vector<char> scoped_array (n+1);
char* pointer = &scoped_array[0];
file.read ( pointer , n );
for (int i = 0; i < n; ++i) {
//do something
}
}
C'est le contraire de ce qu'il veut réellement, cependant. Il veut que ce ne soit pas lancé, tout comme le code de tableau / pointeur ne jette pas.
@Steve Jessop - J'ai lu l'objectif en tant que "réseau dynamique de sécurité exceptionnel en C ++". Le code tel qu'il est présent affirmera (au mieux) et de la faute (plus typiquement).
En ce qui concerne l'exemple de code, je pense que le mot clé est tableau i>. Un tableau fournit un pointeur unébus-gamme, que vous pouvez passer légalement à lire code> tant que le nombre d'octets lus est 0. Un vecteur ne vous donne pas ce pointeur, juste un Un-The-The-The-end itérateur i>. Ainsi, à cet égard, ce n'est pas une matrice dynamique de sécurité d'exception. Je pense que le code de vecteur d'Akusete affirmera ou travaille généralement. Je ne sais pas tout à fait ce que la mise en œuvre ressemble à ce que cela va réellement faire défaut, bien que nous soyons assez sûrs de.
@Steve Jessop - je vois. Ensuite, une solution pragmatique serait peut-être d'une init vecteur avec N + 1 entrées et de contraindre l'accès à 0..n-1 (comme ce code le fait déjà).
@Steve: Bon appel, c'est plus de code concis que ma solution.
Cela a apporté une question intéressante à mon esprit, que j'ai demandé rapidement à ici . Dans votre cas, vous pouvez éviter d'utiliser des pointeurs de la manière suivante: Ceci copiera le contenu du fichier sur un tampon au lieu d'un compteur. P> p> N code> caractères à la fois. Lorsque vous ithétiez sur le tampon, utilisez: p>
En ce qui concerne la norme C ++, Vous vous attendez à ce que dans une implémentation non vérifiée, aller du tableau 68, vous pouvez dire que le résultat de votre expression est J'oublie les résultats de l'argument sur le fait que personnellement, je ne voudrais pas compter à ce sujet, et je ne voudrais pas désactiver la vérification. Je réécrire votre code: p> ou dans ce cas, il suffit de: p> Cela me semble tort de Utilisez Index N d'un vecteur sans savoir que la taille est au moins N + 1, que cela fonctionne si cela fonctionne réellement dans votre implémentation une fois que vous avez désactivé la vérification. P> P> opérateur [] code> n'est pas garanti de ne pas vérifier, c'est juste que (contrairement au
à () code>) il n'est pas garanti de chèque.
& scoped_array [scoped_array.size ()] code> entraînerait un pointeur légal ou un point mort-à-bas d'une Array alloué par le vecteur. Ce n'est pas explicitement garanti, mais pour une mise en œuvre donnée, vous pouvez vérifier en examinant sa source. Pour un vecteur vide, il n'ya peut-être pas d'attribution du tout (comme une optimisation), et je ne vois rien dans le vecteur code> code> de la norme qui définit le résultat de
scoped_array [ 0] code> autre que le tableau 68. P>
& * (A.begin () + 0) code >, qui déréfère illégalement un itérateur hors tension. Si l'itérateur de votre implémentation est juste un pointeur, vous vous enlevez probablement avec ceci - sinon vous ne pourriez pas, et évidemment le vôtre n'est pas. P>
& * code>, sur un pointeur qui ne doit pas être déréférencé, est un non-op, ou non. IIRC n'est pas clair de la norme (une ambiguïté quelque part), qui a provoqué des demandes de fixer la norme pour le rendre explicitement légal. Cela suggère qu'il fonctionne en fait sur toutes les implémentations ou les plus connues. P>
Je suis d'accord, mieux réécrire ce code que d'essayer de contourner le chèque, c'est là pour une raison.
Après tout, quel élément devrait-il faire référence à la référence, quand il n'y a pas d'éléments? Alors oui, vous utilisiez un comportement indéfini tout le long. Les chèques non obligatoires de Visual Studio Studio-mais-match-Comformant dans opérateur [] code> renvoie une référence, et cet invocation à un vecteur vide doit être indéfini. P>
opérateur [] code> devrait renvoyer une référence nulle ou une référence totalement invalide. Les deux résulteraient d'un comportement indéfini. P>
Opérateur [] Code> vient de révéler ce fait. P>
voir LWG Numéro 464 . C'est un problème connu.
C ++ 0x (qui est partiellement implémenté par MSVC 2010) la résout en ajoutant un membre .Data () code>. P>
.Data () serait parfait, dommage que c'est seulement en c ++ 0x
J'accepte cette réponse simplement parce que cela fait référence à la discussion sur la raison pour laquelle ce type d'opération est recherché et ce qui sera (finalement) être un moyen standard de le faire.
Pourriez-vous utiliser des itérateurs au lieu de pointeurs?
{ std::vector<char> scoped_array (size); std::vector<char>::iterator pointer = scoped_array.begin(); //do work } // exception safe deallocation
En général, je cherchais un moyen d'allouer des tableaux de pointeur normaux de manière saine d'exception (en quelque sorte comme auto_ptr pour un tableau). J'étais sous l'impression que c'était une bonne pratique d'utiliser un STD :: Vecteur pour un tel but.
Quelle exception est lancée? Je ne vois rien de mal avec le code.
@Fschmitt: Si le vecteur est vide, alors
Scoped_array [0] code> donne un comportement non défini. Dans ce cas, construire une variante de débogage avec Visual C ++, il échoue à une vérification de la plage et jette une exception.
@Fschmitt: La mise en œuvre de STD STUDIO VISIAL STD :: Vector déclenche une affirmation (c.-à-d. Tue l'ensemble du processus immédiatement) avec une erreur en disant qu'il y avait une erreur hors limites sur le vecteur.
D'accord. Bien sûr, il faut avoir un chèque contre n == 0 dans FOO.