遍历 std::array<char*, N> 的正确方法

Correct way to loop through std::array<char*, N>

考虑以下 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 个元素未正确分配时,这种方法会抛出 "Access violation reading location" 异常。例如,以下代码分配了前两个元素,但第三个元素 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 个元素和数组的最后一个元素以跳过未分配的元素找到了解决此问题的快速解决方案,但显然这不是一个干净的答案

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 {};