在我调用delete,c ++之后仍然可以访问值

时间:2015-12-03 00:20:29

标签: c++ pointers memory heap

我有类,一个Employee类和一个BankAccount类,雇员类将BankAccount类作为私有变量指针。

这就是我想要做的事情:

  1. 我需要使用值
  2. 设置每个BankAccount中的所有Employee s
  3. 然后我会删除该功能结尾的每个BankAccounts的所有Employee
  4. 我在Employee中使用成员函数设置器来设置BankAccount指针。 BankAccount有一个私有变量,即金额。后来我在一个指向每个BankAccount's内存地址的指针上调用delete。在我打电话打印以查看每个Employee的银行值后,它仍然为每个BankAccount打印值

    如果我调用delete,则不应删除堆上的内存,并且在调用print时不输出BankAccount的任何内容?

    以下是代码:

    vector<Employee*> employees;
    
    //get employee full name & salary and return
    employees.push_back(get_employee_info());
    
    //setup their bank account
    setup_bank(employees);
    
    //make temp pointer to store bank memory address
    BankAccount * tempBankPtr;
    
    for (int i =0; i < employees.size(); i++) {
        tempBankPtr =employees[i]->get_bank();
        delete tempBankPtr // delete the heap object that pointer is pointing at
    }
    
    //print values
    for (int i =0; i< employees.size(); i++) {
        employees[i]->print();
    }
    

    打印代码

    void Employee:: print() const {
    
        cout << "First name is: " << firstName << "\n";
        cout << "Last name is: " << lastName << "\n";
        BankAccount* bankholder = NULL;
        bankholder = get_bank();
        if(bankholder != NULL)
        cout << "Account Balance is: " << get_bank()->get_amount() << "\n"; //prints values
    }
    

    银行吸气器

    BankAccount* Employee::get_bank() const{
        return bank;
    }
    

    这在setup_bank中调用

    void Employee::set_bank(Employee* e, double amount){
           bank = new BankAccount(amount);
    }
    

2 个答案:

答案 0 :(得分:10)

  

如果我调用delete,那么堆上的内存是否应该被删除,而当调用print时,不会为BankAccount输出任何东西?

没有

在内存中删除该位置的对象意味着它不再存在,因此您不允许访问它。

It does not mean your program will magically print "nothingness" to protect you from this mistake.

您的程序因此具有未定义的行为; 必须确保不取消引用无效指针!

答案 1 :(得分:1)

关于free如何运作的非常好的解释。

当您在指针上调用delete时,与上面建议的不同,您应该只需要以下

  • 执行析构函数

内存未设置为零或任何其他神奇值,因为这是非常昂贵的操作。当free将被调用时,如果进一步这将导致对sbrk的调用在很大程度上取决于实现。后者将内存返回给操作系统。

例如,众所周知,AIX具有非常复杂的mechanism用于内存管理。您应该期望的是,实际上内存块将被标记为可重新分配,并且新对象可能会在指向地址后覆盖您的内容。在此之前,你的老员工很可能还在那里。

此外,与之前提到的不同,您可以很好地访问它,只要数据段没有减少,实际上对象仍然存在,只有你知道它。 / p>

这就是为什么在这种情况下你没有像你期望的那样得到SIGSEGV。你可能会在以后分配内容时得到它,并且在该内存区域中寻址指针会执行任意代码。

访问删除指针是未定义的行为,第二次删除它更加危险。为了缓解这种情况,有许多技术,最简单的是封装和删除类析构函数上的指针。您应该将指针设置为nullptr。

简单性在这里停止,因为你必须应用rule of three(和一半)。因此,最好使用c ++ 11提供的共享或唯一指针,并暂时忽略这些问题。