众所周知,构造函数和析构函数成对出现.
但是下面的代码不是这样的,构造函数被调用两次但是析构函数只被调用一次!
{
Animal ahe;
ahe = CreateAnimal();
}
Run Code Online (Sandbox Code Playgroud)
请继续阅读以获得更详细的解释.
假设有一个名为Animal的类,我们有以下代码:
int main(int argc, char* argv[])
{
Animal ahe;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
预计Animal的构造函数和析构函数都将被调用一次且仅被调用一次.当我运行代码时,它的行为完全符合我的预期.
但是当涉及到一个函数返回Animal的引用时,它看起来很奇怪.当我运行代码时,构造函数被调用两次,但析构函数只被调用一次!
#include "stdafx.h"
#include "stdio.h"
#include "iostream.h"
class Animal
{
public:
Animal();
Animal(long age);
~Animal();
private:
long m_age;
};
Animal::~Animal()
{
cout<<"Animal::~Animal()"<<"age="<<m_age<<endl;
}
Animal::Animal()
{
m_age = 1;
cout<<"Animal::Animal()"<<"age="<<m_age<<endl;
}
Animal::Animal(long age)
{
m_age = age;
cout<<"Animal::Animal()"<<"age="<<m_age<<endl;
}
Animal& CreateAnimal()
{
Animal *pAnimal = new Animal(5);
return *pAnimal;
}
int main(int argc, char* argv[])
{
Animal ahe;
ahe = CreateAnimal();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
//输出
Animal::Animal()age=1
Animal::Animal()age=5
Animal::~Animal()age=5
Run Code Online (Sandbox Code Playgroud)
显然,没有调用第一个对象的析构函数,为什么?如果Animal有很多需要在析构函数中释放的资源,问题可能会很严重.
您正在通过new在CreateAnimal中创建对象,它将调用构造函数,但您需要显式调用析构函数以获取通过new创建的对象.代码实际上正如预期的那样工作.为两个对象调用构造函数,但是当第一个对象超出范围时,它会在堆栈上调用析构函数,但使用new创建的析构函数永远不会被删除.您需要在其上显式调用delete.
它是调用析构函数的那个对象的副本.当你指定ahe = CreateAnimal(); 在堆栈上创建副本,因为它不是引用
Animal ahe; // -> constructor called for object on stack
ahe = CreateAnimal(); // -> constructor called due to new call and ahe created in previous //line replaced with the object created via new
} // main method ends, ahe goes out of scope and it's destructor is called but since //it now contains a copy of the object created via new, it prints 5
Run Code Online (Sandbox Code Playgroud)
如果您不想记住为使用new创建的每个对象调用delete,则只需使用auto_ptrs.