访问 2D 向量数组时范围的分段 Fault/Out

Segmentation Fault/Out of Range on accessing a 2D vector array

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

using namespace std;

int main()
{

        int m, n;
        cin>>m>>n;
        vector <vector<char>> mine(n);

    for( int i = 0; i < m; i++)
    {
        vector<char> row;
        for( int i = 0; i < n ; i++)
        {
            char x;
            cin>>x;
            row.push_back(x);
        }
    }

  cout<<mine.at(0).at(0)<<endl;
  cout<<mine.at(-1).at(-1)<<endl;
  cout<<mine.at(3).at(3)<<endl;

}

当我使用我的 [0][0] 而不是使用 at 成员函数时,我的代码在线上给出了分段错误。

cout<<mine.at(0).at(0)<<endl;

现在它给了我

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)

至于我为什么要访问-1 索引,我只是想检查向量是否会忽略它。虽然我不知道为什么它在访问第 0 个索引时遇到问题。

cout<<mine.at(0).at(0)<<endl; 尝试访问 mine 中第一个 vector<char> 的第一个元素,但第一个 vector<char> 不包含任何元素。这就是为什么在尝试使用 operator[] 访问该元素时出现分段错误,或者在尝试使用 at() 方法访问该元素时出现 std::out_of_range 异常。

您的代码有几个问题:

  • 当您创建 mine 向量时,它只包含 n 个空的 vector<char>
  • 然后在外部 for 循环的每次迭代中创建一个 row 向量。但是该向量与 mine 向量完全没有联系。此外,row 向量在外部 for 循环的每个循环结束时被销毁。
  • 当您打印出 mine 的内容时,mine 包含 n 个空向量。
    • mine.at(0) 将为您提供第一个空向量(如果 n >= 1),但 mine.at(0).at(0) 将失败并出现超出范围的异常,因为第一个空向量中没有任何内容。
    • -1 索引不会被忽略。 如果你看一下 at 方法参考(https://en.cppreference.com/w/cpp/container/vector/at), you'll see that it receives a std::size_t, an unsigned integer. So integer -1 is actually converted to a very large unsigned integer index. Check error message here: https://godbolt.org/z/xxfGhP7zq
    • 如果 n < 3
    • mine.at(3) 可能会失败,因为您正试图访问 mine 处的第四个空向量。如果没有失败,mine.at(3).at(3) 将因与 mine.at(0).at(0) 相同的原因而失败。在此处检查错误消息:https://godbolt.org/z/csz6TrYf4

下面的代码解决了这些问题:https://godbolt.org/z/a63GrW8Tx

  • 它创建了一个 mine 向量 m vector<char>s 大小 n,即 space n 个字符。

  • 在外部 for 循环中,它获取对 mine[i] 的引用,当前 vector<char>.

  • 然后它用 row[j] 填充访问每个 char 的向量。由于我们正在处理对 mine 中向量的引用,因此我们正在修改 mine.

  • 我觉得对索引使用不同的名称更清楚。

  • 我已经注释掉了超出范围的访问。如果你想避免它们,你应该根据向量大小检查你的索引。或者只处理异常。

    #include <iostream>
    #include <string>
    #include <vector>
    
    int main()
    {
        int m;
        int n;
        std::cin >> m >> n;
        std::vector<std::vector<char>> mine(m, std::vector<char>(n));
    
        for (int i{0}; i < m; i++)
        {
            auto& row = mine[i];
            for (int j{0}; j < n ; j++)
            {
                char x;
                std::cin >> x;
                row[j] = x;
            }
        }
    
        std::cout << mine.at(0).at(0) << "\n";
        //std::cout << mine.at(-1).at(-1) << "\n";  // out of range exception
        if (-1 < mine.size() and -1 < mine.at(-1).size())
        {
            std::cout << mine.at(-1).at(-1) << "\n";
        }
        //std::cout << mine.at(3).at(3) << "\n";  // out of range exception
        try
        {
            std::cout << mine.at(3).at(3) << "\n";
        }
        catch (const std::out_of_range& ex)
        {
            std::cout << "Error: " << ex.what();
        }
    }