【问题标题】:c++ right way to initialize a vector of a structc ++初始化结构向量的正确方法
【发布时间】:2016-09-09 10:26:20
【问题描述】:

我在这里搜索了很多,但对于我来说,对于 c++ 的高级新手来说,没有正确的解释。我以前使用结构向量,现在我遇到分段错误......

这就是为什么我想知道这些对象实际上是如何工作的,以及我的做法是否正确!

我有一个类似的结构

struct numberOfSpecies {
   int predator;
   int prey1;
   int prey2;
};

以及它的向量:

std::vector<numberOfSpecies> size;

在我调整它的大小并用值填充它之前。

size.resize(100);

这实际上是在做什么?这适合结构吗? 好像是用零初始化的……

现在我正在这样做:

size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;

for(int k = 0; k < N; ++k){
  size[t].predator++;
  size[t].prey1++;
  size[t].prey2++;
}

这是对的吗?可能的问题在哪里?如何做得更好?

【问题讨论】:

  • resize 创建n 结构数,但您的结构仅在意外情况下被初始化为 0(因为您使用调试模式)。你应该假设每个值在调整你使用它的方式后都有一个随机的未定义值。
  • 可以帮忙:t 的价值是什么?分段错误发生在哪里?你能添加更多代码吗?最好以stackoverflow.com/help/mcve 方式
  • @Hayt 你确定在 0 初始化是个意外吗?我一直认为 resize 调用对象的构造函数,所以在这种情况下,默认一个,它将每个成员都设置为 0
  • @Hayt: std::vector 将value-initialize结构而不是default-initialize结构。所以对于 POD 来说,就是零初始化。
  • 你希望数组的每个元素在初始化结束时包含什么?

标签: c++ vector struct


【解决方案1】:

这里最简单和“正确”的解决方案可能只是使用属于带有聚合初始化的向量对象的resize() 函数(如果您可以访问 c++11 及更高版本),类似于

size.resize(100,{0,0,0}); //aggregate initialization 

for(int k = 0; k < N; ++k)
{
    size[t].predator++;
    size[t].prey1++;
    size[t].prey2++;
}

每个numberOfSpecies对象的所有成员都将被初始化为0。

【讨论】:

  • “中间”选项是reserve 和push_back。但是如果你想用默认值初始化所有东西resize这里更好。
  • 我认为您不需要{0,0,0}(尽管它不会造成伤害)作为resize 的第二个参数,因为默认情况下std::vector::resize 执行默认初始化,这对于聚合,表示zero-initialization。
  • @vsoftco 我刚刚包含它以显示语法,以防他出于任何原因将成员初始化为不同的值,或者如果其他人查找问题。跨度>
【解决方案2】:

这个:

size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;

将向size 的tth 元素写入零 - 这可能有用也可能没用:

这个:

for(int k = 0; k < N; ++k){
  size[t].predator++;
  size[t].prey1++;
  size[t].prey2++;
}

将增加size 的tth 元素N 次。这似乎不太可能有用。我想你想要的是:

size[0].predator=0;  // Technically not needed because .resize()
size[0].prey1=0;     // will have initialized it to zero anyway
size[0].prey2=0;     // *BUT* explicit is always better than implicit.

// Initialize each element of size to be one greater than previous.
for(int k = 1; k < N; ++k){
  size[k].predator = size[k-1].predator + 1;
  size[k].prey1    = size[k-1].prey1    + 1;
  size[k].prey2    = size[k-1].prey2    + 1;;
}

【讨论】:

    【解决方案3】:

    静态参数使用value参数。

    #include <vector>
    
    struct foo{
        int g;
        int h;
        int l;
    };
    
    int main()
    {
        std::vector<foo> manyFoo(10, {0});
        manyFoo.resize(60, {0});
    } 
    

    如果你想增加你的向量,你也可以将任意值放入结构中 ->

    #include <iostream>
    #include <vector>
    
    struct foo{
        foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
        int g;
        int h;
        int l;
    };
    
    int main() {
        std::vector<foo> lVec;
        for (int i=0;i<10;i++) {
            lVec.emplace_back(foo(i,i*2,i*4));
        }
        int lPos=0;
        for (auto &rFoo: lVec) {
            std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
        }
        return EXIT_SUCCESS;
    }
    

    如果您知道向量的大小并且想要填充它,您可以 ->

    #include <iostream>
    #include <vector>
    
    struct foo{
        foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
        int g;
        int h;
        int l;
    };
    
    int main() {
        std::vector<foo> lVec(10,{0,0,0});
        int lPos = 0;
        for (auto &rFoo: lVec) {
            rFoo = foo(lPos,lPos*2,lPos*4);
            lPos++;
        }
        lPos=0;
        for (auto &rFoo: lVec) {
            std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
        }
        return EXIT_SUCCESS;
    }
    

    【讨论】:

      【解决方案4】:

      您可以在结构中添加默认构造函数。新代码将如下所示:

      struct numberOfSpecies {
          numberOfSpecies (): predator(0), prey1(0), prey2(0) { }  // default constructor
          int predator;
          int prey1;
          int prey2;
      };
      

      这样,当应用调整大小时,您的结构将在矢量内正确初始化。

      【讨论】:

      • 或者,使用 c++11:struct numberOfSpecies { int predator = 0; int prey1 = 0; int prey2 = 0; };
      • 根据“正确初始化”,没有构造函数也是如此。您的构造函数仅显式 0,但根据 resize 规范,它已经在向量内正确初始化为零。只有在默认情况下您想要 0 以外的值时才会感兴趣
      • @Garf365 或者,至少从 C++03 开始​​,只需将构造函数排除在外,因为在这种情况下它没有任何区别 :-)
      猜你喜欢
      • 2011-08-20
      • 2019-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多