为什么在使用赋值时不为堆栈变量调用析构函数?

问题描述 投票:3回答:2

这个愚蠢的代码已经花了我2个小时,我不知道为什么第一个元素的析构函数(大小为7的析构函数没有被调用?为new uint16_t[7]分配的内存会怎样?

#include <iostream>

using namespace std;

struct Node
{
    Node(uint16_t n) : p(new uint16_t[n]) {
        cout<<"Constructed with size= "<<n<<", memory addr: "<<(p)<<endl;
        for(uint16_t i=0; i<n; i++) p[i] = n;
    }

    ~Node() {
        cout<<"Destructor for p[0] = "<< *p <<" with memory addr: "<<p<<endl;
        delete[] p;
    }

    uint16_t *p;
};

int main()
{
    {
        Node nd1(7);
        {
            nd1 = Node(3);
            cout << "1st place holder" << endl;
        }
        cout << "2nd place holder" << endl;
    }

    return 0;
}

输出为

Constructed with size= 7, memory addr: 0x158cc20                                                                                                                                   
Constructed with size= 3, memory addr: 0x158cc40                                                                                                                                   
Destructor for p[0] = 3 with memory addr: 0x158cc40                                                                                                                                
1st place holder                                                                                                                                                                   
2nd place holder                                                                                                                                                                   
Destructor for p[0] = 0 with memory addr: 0x158cc40                                                                                                                                
*** Error in `./a.out': double free or corruption (fasttop): 0x000000000158cc40 ***                                                                                                
Aborted (core dumped) 
c++ destructor
2个回答
4
投票

我不知道为什么第一个元素的析构函数,大小为7的析构函数没有被调用?

被调用。实际上,正是那个析构函数导致程序崩溃。该行为是未定义的,因为析构函数将删除先前由临时对象的析构函数删除的指针值。并且在此之前,它通过该无效指针进行间接访问。


分配给新uint16_t [7]的内存会怎样?

分配给对象时,指向内存的指针丢失。这称为内存泄漏。


2
投票

此代码:nd1 = Node(3);不是您所期望的。

[不是nd1替换Node(3)并杀死旧的nd1

它的作用是创建一个新的临时节点实例Node(3),并将每个成员的值复制到nd1中。因此,临时和nd1都包含指向同一地址的指针。那时,由于没有指针引用程序,但是没有删除它,因此泄漏了在程序开始时分配的内存nd1

[当临时对象死亡时,nd1指向死内存。当nd1在第二个}上运行其析构函数时,它将再次删除相同的指针,因此会导致您的错误。

© www.soinside.com 2019 - 2024. All rights reserved.