考虑以下std::array的char指针。
std::array<char*, 10> m_arr;
我知道我可以用下面的代码来循环浏览这个数组。
for(size_t i {0}; i < m_arr.size(); i++) {
std::cout << m_arr.at(i) << std::endl;
}
但是这种方法会抛出 "访问违规读取位置 "的异常,当第i-th元素没有正确分配时。例如下面的代码分配了前两个元素,但第三个元素。m_arr.at(3)
引起上述错误。
// 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;
}
我找到了一个快速的解决方法,用数组的最后一个元素来检查第i-th个元素,以跳过未分配的元素,但显然这不是一个简单的答案。
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;
}
}
我相信有更好的方法来循环这个数组,避免错误。先谢谢您的帮助。
初始化你的数组。
std::array<char*, 10> m_arr{}; // nullptr initialized
然后你可以检查非nullptr值的安全性:
for (auto ptr : m_arr) {
if (ptr) std::cout << ptr << std::endl;
}
问题并不在于你迭代数组的方式, 而是数组包含的内容, 以及你如何处理这些内容: 问题在于你只初始化了数组中的两个指针。读取值,并间接通过未初始化的指针导致未定义的行为。
这里有一个正确的方法,就是只循环处理初始化的元素,依靠你已经初始化了前两个元素的知识。
for(size_t i {0}; i < 2; i++) {
另一种方法是将其他指针初始化为空,然后在循环条件中检查。
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';
我比较喜欢这种类型的迭代。
#include <iostream>
#include <array>
using namespace std;
// ...
for (auto&& object : m_arr)
{
cout << (object != nullptr ? object : "Null pointer") << endl;
}
不要忘了初始化你的数组,这将为你节省一些分段错误。
std::array<char*, 10> m_arr {};