在循环中初始化预分配的struct实例

时间:2013-05-02 11:49:39

标签: c++ loops struct instance

我想使用malloc()为特定结构的特定数量的实例分配内存。 然后,我想在循环中初始化每个实例。 但是,对于每次迭代,我观察构造函数和之后的析构函数被称为...为什么? 令我感到惊讶的是,尽管调用了析构函数,我的每个实例都存在于循环之后...并且我的实例被初始化为相同的值! 我明确地错过了一些重要的事情...如果有人可以帮助我,我将不胜感激,因为现在,我无法解释发生了什么。 这是我的C ++代码:

struct myStruct{
   int* a;
   int* b;
   myStruct(int x, int y)
   {
    std::cout << "the constructor is called" << std::endl;
    a = (int*)malloc(x*sizeof(int));
    b = (int*)malloc(y*sizeof(float));
   }
   ~myStruct()
   {
       std::cout << "the destructor is called" << std::endl;
       delete[] a;
       delete[] b;
   } };

int main(int argc, char** argv){
int Nb = 3;
myStruct *S = (myStruct*)malloc(Nb*sizeof(myStruct));
for(int i=0 ; i<Nb ; i++)
{
    *(S+i) = myStruct(1,2);
}
std::cout << std::endl;
for(int i=0 ; i<Nb ; i++)
{
    std::cout << "instance " << i << " :" << std::endl;
    std::cout << (unsigned int)(*(S+i)->a) << std::endl;
    std::cout << (unsigned int)(*(S+i)->b) << std::endl << std::endl;
}
system("PAUSE");}

我的命令窗口显示:

构造函数被称为

析构函数被称为

构造函数被称为

析构函数被称为

构造函数被称为

析构函数被称为

实例0: 1608524712 4277075694

实例1: 1608524712 4277075694

实例2: 1608524712 4277075694

按任意键继续。 。

最好的问候

2 个答案:

答案 0 :(得分:0)

在表达式

*(S+i) = myStruct(1,2)

您所做的就是创建结构的临时实例(myStruct(1,2)部分),然后该实例复制到S[i]。副本很浅,因此只复制指针并且不分配或复制新数据。表达式完成后,不再需要临时实例,因此它被破坏了。

这种破坏当然会导致数据成员的释放,因此数组中结构中的指针(副本)不再有效,访问它们是未定义的行为。此外,您实际上并没有将分配的内存初始化为任何内容,因此内存将包含分配之前的内容,内容看起来是随机的。

我建议您阅读std::vectorstd::shared_ptr,最重要的是the rule of three

答案 1 :(得分:0)

每次循环时,代码都会创建一个临时对象(myStruct(1,2))然后销毁它。这就是输出显示的内容。

该临时对象被分配给未初始化的对象*(S+i),这不是一件好事。对象应该由构造函数初始化,而不是赋值运算符。在这里使用构造函数的方法是placement new:

new (S+i) myStruct(1,2);

括号中的第一个值是构造对象的地址。

完成此操作后,正如其他人所提到的那样,您不能在生成的数组上使用delete,因为它不是使用new创建的。所以你必须遍历对象并在每个对象上显式调用析构函数,然后free内存。