c++结构,如何动态创建结构对象,

c++ struct, how to create struct objects dynamically,

本文关键字:结构 创建 对象 动态 何动态 c++      更新时间:2023-10-16

我有一个这样的结构:

struct MYSTRUCT {
    ....
};

如果我用如下的for循环创建结构对象:

for(int i = 0; i < 2; i++){
    MYSTRUCT *mystruct;
}

mystruct每次都会因为相同的名称而相同吗?上面的代码和这个代码有什么区别:

MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1; 

如何以更简单的方式创建不同的结构对象?

MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1;
...
MYSTRUCT *mystruct99;
MYSTRUCT *mystruct100; 

如果我按照下面的方式操作,所有的结构指针是相同的还是相互隔离的?

vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
    MYSTRUCT *mystruct;
    mystructs.push_back();
}

首先,您不应该尝试生成变量名。这不是办法。

你应该使用一个容器(比如你的例子中的std::vector),它正是你想要的:用来放置其他几个相同类型的东西。

在您的示例中:

struct MyStruct {  // Don't name your struct in all caps.
                   // it's generally reserved for MACROS. Use CamelCase
    // blablabla
}

除非需要,否则不要使用指针,通常使用值会更容易更高效。如果您需要将向量的一个元素传递给一个函数,以便该函数可以修改它,那么您可以将迭代器传递给该元素。

vector<MyStruct> mystructs;
for(int i = 0; i < 100; i++){
    mystructs.emplace_back(MyStruct{});
}

此外,如果结构中有需要初始化的字段,则可能需要使用初始值设定项列表或定义构造函数。

如果你需要使用动态分配,你可以这样做:

vector<MyStruct*> mystructs;
for(int i = 0; i < 100; i++){
    mystructs.emplace_back(new MyStruct{});
}

现在矢量包含指针,而不是对象。每个物体都被单独分配到自己的记忆位置,因此它们不可能相邻。这对性能非常重要:指针为您提供间接性。间接导致痛苦。痛苦导致愤怒。。。blablabla=>欢迎来到黑暗面。

struct是您定义的数据类型,当您执行MYSTRUCT *mystruct时,您声明一个指向MYSTRUCT对象的指针,该指针称为mystruct。这与使用int *pointer_to_int相同。

对于第一个版本,在每次迭代时重新声明mystruct,而第二个版本则声明两个独立变量。如果您想简单地声明一组MYSTRUCT*,请使用一个MYSTRUCT*:MYSTRUCT* mystruct_pointers_array[100]数组。

注意MYSTRUCT*指针不同于MYSTRUCT变量,您需要取消引用该指针才能访问MYSTRUCT元素。例如mystruct->x

在您的示例代码中:

for(int i = 0; i < 2; i++){
    MYSTRUCT *mystruct;
}

您根本没有创建对象。您所要做的只是声明指向MYSTRUCT指针。这些指针是未初始化的,因此(还)不指向任何东西。此外,指针(mystruct)本身是在堆栈上分配的,其生存期限制在for循环的范围内。

我不确定您想要实现什么,但如果您需要MYSTRUCT类型的多个对象,则不应该尝试在这样的循环中创建它们。相反,声明一个数组或std::vector并进行适当的初始化。我会让你想办法做这件事。当您这样做时,请注意静态数组和动态数组之间的区别,以及它们对内存管理的影响!

编辑:应要求,我将详细说明您提供的最后一个片段:

vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
    MYSTRUCT *mystruct;
    mystructs.push_back();
}

这里发生的是,您声明了一个指向MYSTRUCT的空指针向量。到目前为止还不错。现在,从主体上判断,您希望用指向实际对象的指针填充这个向量,但这在您的代码中没有发生。考虑到push_back需要一个MYSTRUCT*作为参数,我甚至怀疑它是否会编译。因此,要做您打算做的事情,您的代码应该在每次迭代中:

  1. 在堆上分配一个对象
  2. 将指向该对象的指针推到向量的后面

如下所示:

vector<MYSTRUCT*> vec;
for (int i = 0; i != n; ++i) // pre-incr is good practice!
    vec.push_back(new MYSTRUCT); // optionally add constructor arguments 

然而,这会给您带来新的责任:您是使用new显式请求内存的人,因此您应该使用delete显式释放内存。除非MYSTRUCT是多态的(包含虚拟成员),否则您可以很容易地绕过它(即使它多态的,您也不应该这样做,但这是另一个主题)。

这个问题的答案是:不存储指针,存储对象:

vector<MYSTRUCT> vec; // no pointer!
for (int i = 0; i < 100; ++i)
    vec.push_back(MYSTRUCT()); // create an unnamed instance and copy to the back of the vec

在那里,您刚刚创建了n MYSTRUCT实例的向量。没有指针,没有newdelete,简单易用!

为此使用std::矢量:

std::vector<MYSTRUCT *> v(100);
for (auto& pointer : v)
   pointer = new MYSTRUCT(/*...*/); //initializating (writing address to pointer)

按照您的方式,您只需初始化指针类型的对象。换句话说,您只为指针分配内存,在指针中必须将地址写入结构或nullptr-value。

其他人也说过类似的话,但特别是我会这样做:

std::vector <MYSTRUCT *> vect;
for(int i = 0; i < 2; i++){
    vect.push_back();
}

然后,您可以像访问数组一样访问每个元素,如vect[0]。再加上使用std::vector,您可以使用vect.front()访问第一个元素(元素0),使用vect.back()访问最后一个元素。

尽管不分配单独初始化的MYSTRUCT是无用的,但我可以看到struct *向量的有用性。