Considérez le std :: tableau de pointeurs vers char suivant:
for(size_t i {0}; i < m_arr.size(); i++) { if(m_arr.at(i) != m_arr.back()) { std::cout << m_arr.at(i) << std::endl; } }
Je sais que je peux parcourir le tableau en utilisant le code suivant
// test variables int x {100}; double y {3.14}; int* x_ptr {&x}; double* y_ptr {&y}; // std::array of pointer to char std::array<char*, 10> m_arr; // set the first two elements of m_arr char buf1[16]; sprintf_s(buf1, "%p", x_ptr); m_arr.at(0) = buf1; char buf2[16]; sprintf_s(buf2, "%p", y_ptr); m_arr.at(1) = buf2; for(size_t i {0}; i < m_arr.size(); i++) { std::cout << m_arr.at(i) << std::endl; }
Mais cette approche lève l'exception "Emplacement de lecture de violation d'accès", lorsque le i-ème élément n'est pas affecté correctement. Par exemple, le code suivant attribue les deux premiers éléments mais le troisième élément, m_arr.at (3)
, déclenche l'erreur susmentionnée:
for(size_t i {0}; i < m_arr.size(); i++) { std::cout << m_arr.at(i) << std::endl; }
I a trouvé une solution rapide à ce problème en vérifiant le i-ème élément avec le dernier élément du tableau pour ignorer les éléments non attribués, mais ce n'est évidemment pas une réponse claire
std::array<char*, 10> m_arr;
Je crois qu'il y a est un meilleur moyen de parcourir ce tableau et d'éviter l'erreur. Merci d'avance pour votre aide.
3 Réponses :
Initialisez votre tableau:
for (auto ptr : m_arr) { if (ptr) std::cout << ptr << std::endl; }
alors vous pouvez vérifier la sécurité pour une valeur non-nullptr:
std::array<char*, 10> m_arr{}; // nullptr initialized
@NathanOliver: corrigé.
Le problème n'est pas tant la manière dont vous itérez le tableau, mais plutôt ce que le tableau contient et ce que vous faites avec ce contenu: le problème est que vous n'avez initialisé que deux des pointeurs du tableau. La lecture de la valeur et le fait de passer par les pointeurs non initialisés entraînent un comportement indéfini.
Voici une façon correcte de parcourir uniquement les éléments initialisés, en vous appuyant sur le fait que vous avez initialisé les deux premiers:
std::array<char*, 10> m_arr{}; // value initialisation ... for(size_t i {0}; i < m_arr.size() && m_arr[i]; i++) { // or with range-for: for (char* ptr : m_arr) { if (!ptr) break; std::cout << ptr << '\n';
Une autre approche consiste à initialiser les autres pointeurs à null, et à vérifier cela dans la condition de boucle:
for(size_t i {0}; i < 2; i++) {
Je suis plus fan de ce type d'itération:
std::array<char*, 10> m_arr {};
N'oubliez pas d'initialiser votre tableau aussi, cela vous évitera quelques défauts de segmentation:
#include <iostream> #include <array> using namespace std; // ... for (auto&& object : m_arr) { cout << (object != nullptr ? object : "Null pointer") << endl; }
@Blastfurnance Mon erreur, vous avez raison. Je vais ajouter ma réponse
Je ne pense pas que votre «solution» corrige quoi que ce soit. Quoi qu'il en soit, le problème n'est pas de boucler sur l'élément. Il s'agit de dé-référencer des pointeurs non initialisés.
Lorsque vous savez que l'index sera valide, il n'y a rien de mal à utiliser
operator []
au lieu deat
. En principe,at
a la charge de vérifier l'index à chaque fois qu'il est appelé.La première question serait: pourquoi utilisez-vous
char *
au lieu destd :: string
?@UnholySheep C'est probablement le cas où une fonction API sous-jacente ou similaire utilise
char *
, et l'OP suppose qu'ils doivent également utiliserchar *
dans leur programme pour communiquer avec le API. J'ai vu cette hypothèse erronée trop souvent pour ne pas la remarquer.@UnholySheep C'est un peu compliqué mais std :: string n'est pas une option
@ FrançoisAndrieux Merci. Je ne savais pas ça.