我想使用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
按任意键继续。 。
最好的问候
答案 0 :(得分:0)
在表达式
中*(S+i) = myStruct(1,2)
您所做的就是创建结构的临时实例(myStruct(1,2)
部分),然后将该实例复制到S[i]
。副本很浅,因此只复制指针并且不分配或复制新数据。表达式完成后,不再需要临时实例,因此它被破坏了。
这种破坏当然会导致数据成员的释放,因此数组中结构中的指针(副本)不再有效,访问它们是未定义的行为。此外,您实际上并没有将分配的内存初始化为任何内容,因此内存将包含分配之前的内容,内容看起来是随机的。
我建议您阅读std::vector
,std::shared_ptr
,最重要的是the rule of three。
答案 1 :(得分:0)
每次循环时,代码都会创建一个临时对象(myStruct(1,2)
)然后销毁它。这就是输出显示的内容。
该临时对象被分配给未初始化的对象*(S+i)
,这不是一件好事。对象应该由构造函数初始化,而不是赋值运算符。在这里使用构造函数的方法是placement new:
new (S+i) myStruct(1,2);
括号中的第一个值是构造对象的地址。
完成此操作后,正如其他人所提到的那样,您不能在生成的数组上使用delete
,因为它不是使用new
创建的。所以你必须遍历对象并在每个对象上显式调用析构函数,然后free
内存。