c ++初始化结构向量的正确方法

Posted

技术标签:

【中文标题】c ++初始化结构向量的正确方法【英文标题】:c++ right way to initialize a vector of a struct 【发布时间】: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 的价值是什么?分段错误发生在哪里?你能添加更多代码吗?最好以***.com/help/mcve 方式 @Hayt 你确定在 0 初始化是个意外吗?我一直认为 resize 调用对象的构造函数,所以在这种情况下,默认一个,它将每个成员都设置为 0 @Hayt: std::vectorvalue-initialize结构而不是default-initialize结构。所以对于 POD 来说,就是零初始化。 你希望数组的每个元素在初始化结束时包含什么? 【参考方案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。

【讨论】:

“中间”选项是reservepush_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;

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

这个:

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

将增加sizetth 元素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 开始​​,只需将构造函数排除在外,因为在这种情况下它没有任何区别 :-)

以上是关于c ++初始化结构向量的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

C语言中结构体初始化的方法

如何正确初始化 C++11 中的数据成员?

初始化一个非常大的结构的正确方法是啥?

初始化结构向量向量的好方法(每个都有一个初始值)?

在c中初始化双指针的正确方法是啥

结构体初始化