【问题标题】:Trying to dynamically allocate an array inside an element of a vector of structs尝试在结构向量的元素内动态分配数组
【发布时间】:2020-12-22 00:38:10
【问题描述】:

我有一个点类型的向量(点是一个包含 2 个整数和一个指向 int, s 的指针的结构),我正在尝试为 s 数组(malloc / new)动态分配内存并向其添加两个值但它给了我段错误。我不知道是否允许我在向量元素内执行此操作。提前谢谢你。

struct point{
    int x, y;
    int *s;
};

int main(void){

    int n, val1, val2, val3, val4, i;
    vector<point> v;

    v.resize(2);
    cin >> n;
    for(i = 1; i <= n; i++)
    {
        cin >> val1 >> val2 >> val3 >> val4;
        v[i - 1].x = val1;
        v[i - 1].y = val2;
        v[i - 1].s = new int[2]; // here i think is the problem.
        //v[i - 1].s = (int *)malloc(2 * sizeof(int));
        v[i - 1].s[0] = val3;
        v[i - 1].s[1] = val4;
    }
    for(i = 0; i <= v.size(); i++)
    {
        cout << v[i].x << " " << v[i].y << " " << v[i - 1].s[0] << " " << v[i - 1].s[1] ;
        cout << "\n";
    }
    return 0;
}

【问题讨论】:

  • 为什么不改用std::vector&lt;int&gt; s;?另外,如果n 大于您在v 中设置的位置,会发生什么情况?为什么i - 1 而不是在0 开始循环?
  • s 中是否总是有 2 个整数?如果是这样,std::array&lt;int,2&gt; 可能更合适。
  • i &lt;= v.size() 看起来像一个错误。 v[v.size()] 是向量末尾之后的一个元素。当i 为0 时,v[i - 1] 也是一个错误。

标签: c++ arrays vector dynamic-memory-allocation


【解决方案1】:
  • 你不resize() vectorn。您有一个固定值2。一旦有人在std::cin &gt;&gt; n 中输入大于2 的内容,这将使程序具有未定义的行为。
  • 第二个循环for(i = 0; i &lt;= v.size(); i++) 将使程序访问v[v.size()] 越界,因此您的程序具有未定义的行为。
  • 循环for(i = 1; i &lt;= n; i++) 没有错,因为您在循环内使用i - 1 进行补偿,但这是不必要的。执行 for(i = 0; i &lt; n; i++) 或使用基于范围的 for 循环(如下所示)。
  • 不要将new 用于s。使用固定大小的std::array&lt;int, 2&gt; 或您可以调整大小的std::vector&lt;int&gt;

例子:

#include <iostream>
#include <vector>

struct point {
    int x, y;
    std::vector<int> s; // use a vector instead of a raw pointer
};

int main() {   // not main(void)
    int n, val1, val2, val3, val4;
    std::vector<point> v;

    if(!(std::cin >> n)) return 1; // extraction may fail

    v.resize(n); // resize it appropriately

    // you can access the `point`s in the vector using a range based for-loop:
    for(point& p : v) {
        if(std::cin >> val1 >> val2 >> val3 >> val4) { // check if extraction succeeded
            p.x = val1;
            p.y = val2;
            p.s.resize(2);
            p.s[0] = val3;
            p.s[1] = val4;
        } // else /* break, return 1, ... something */
    }

    // You can also access the elements like this, but pay attention
    // to the condition: i < v.size()
    for(int i = 0; i < v.size(); i++) {
        std::cout << v[i].x << ' ' << v[i].y << ' '
                  << v[i].s[0] << ' ' << v[i].s[1] << '\n';
    }
}

另一种选择是 resize() v,只需使用emplace_back 向其添加新的points。注意内部 vectors 是如何自动调整大小的:

    for(int i = 0; i < n; ++i) {
        if(std::cin >> val1 >> val2 >> val3 >> val4) {
            v.emplace_back(point{val1, val2, {val3, val4}});
        } else
            break;
    }

还请注意,在不检查它是否确实具有 2 元素的情况下访问 v.s[0]v.s[1] 有点冒险,但如果您知道在您的初始循环之后总是如此,它应该没问题。

【讨论】:

  • 起初我只使用了 2 个元素插入向量中(从这里 v.resize(2) 开始),然后当我切换到 n 时,我忘了更改它。我真的理解你的两个解决方案,确实使用vectors而不是int *s更好,但我仍然习惯了C的做事方式。
  • @StefanSs 是的,从 C 到 C++ 时,这部分也花了我一段时间——但你走在正确的轨道上,因为你已经为 v 使用了 vector - 和范围基于 for 循环真的很整洁。在使用它们时必须遍历循环中的所有元素时,很少会出错。
【解决方案2】:

这个

    v[i - 1].s = new int[2]; // here i think is the problem.
    v[i - 1].s[0] = val3;
    v[i - 1].s[1] = val4;

不是的问题。 s 是向量中元素的成员这一事实并不重要。上面是这样正确的:

int* s;
s = new int[2]; // here i think is the problem.
s[0] = val3;
s[1] = val4;

这是一个问题,因为不清楚为什么要在这里使用手动分配的数组。当我在同一个代码中看到std::vectornew int[2] 时,我总是有点困惑。从向量中,您可以获得从动态分配的数组中获得的一切等等。无论如何,导致段错误的问题在其他地方......

v.resize(2);
cin >> n;
for(i = 1; i <= n; i++)
{
    cin >> val1 >> val2 >> val3 >> val4;
    v[i - 1].x = val1;
    ....

v 有 2 个元素。在您的代码中,元素的数量没有任何变化。当用户为n 输入大于 2 的值时,您将访问超出范围的向量。越界访问是未定义的行为。运行代码时,任何事情都可能发生。

你的最后一个循环也是错误的。最后一个有效索引是v.size()-1。通常使用半开区间,即包含开头,不包含结尾:

 for(i = 0; i < v.size(); i++)
         //   ^^ not <= !!!

【讨论】:

  • 我使用 new 是因为我习惯了 C,在 C 中你必须使用 malloc、realloc、calloc 动态分配数组。现在我开始了解向量。确实,我犯了一些大错。 "
  • @StefanSs 在现代 C++ 中相当罕见,您必须使用 new。容器和智能指针涵盖了大多数动态分配情况
猜你喜欢
  • 2019-07-19
  • 2021-02-20
  • 2015-05-17
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多