指针与对象
不管是类还是结构(其实结构是一种特殊的类),它们在创建时还是要创建内存的,但是,创建类的对象也有两种方式,直接声明和用指针来分配新实例。
- #include <iostream>
- using namespace std;
- class Test
- {
- public:
- Test();
- ~Test();
- void Do(char* c);
- };
- Test::Test()
- {
- cout << "Test对象被创建。" << endl;
- }
- Test::~Test()
- {
- cout << "Test对象被销毁。" << endl;
- }
- void Test::Do(char* c)
- {
- cout << "在" << c << "中调用了Do方法。" << endl;
- }
- void Func1()
- {
- Test t;
- t.Do("Func1");
- /*
- 当函数执行完了,t的生命周期结束,发生析构。
- */
- }
- void Func2()
- {
- Test* pt = new Test;
- pt -> Do("Func2");
- /*
- 用指针创建的对象,就算指针变量的生命周期结束,但内存中的对象没有被销毁。
- 因此,析构函数没有被调用。
- */
- }
- int main()
- {
- Func1();
- cout << "---------------------" << endl;
- Func2();
- getchar();
- return 0;
- }
我们来看看这个例子,首先定义了一个类Test,在类的构造函数中输出对象被创建的个息,在发生析构时输出对象被销毁。
接着, 我们分别在两个函数中创建Test类的对象,因为对象是在函数内部定义的,根据其生命周期原理,在函数返回时,对象会释放,在内存中的数据会被销毁。理论上是这样的,那么,程序实际运行后会如何呢?
这时候我们发现一个有趣的现象,在第一个函数直接以变量形式创建的对象在函数执行完后被销毁,因为析构函数被调用;可是,我们看到第二个函数中并没有发生这样的事,用指针创建的对象,在函数完成时居然没有调用析构函数。
直接创建对象,变量直接与类实例关联,这样一来,当变量的生命周期结束时,自然会被处理掉,而用指针创建的实例,指针变量本身并不存储该实例的数据,它仅仅是存了对象实例的首地址罢了,指针并没有与实例直接有联系,所以,在第二个函数执行完后,被销毁的是Test*,而不是Test的对象,仅仅是保存首地址的指针被释放了而已,而Test对象依然存在于内存中,因此,在第二个函数完成后,Test的析构函数不会调用,因为它还没死呢。
那么,如何让第二个函数在返回时也销毁对象实例呢?还记得吗,我前文中提过。对,用delete.。
- void Func2()
- {
- Test* pt = new Test;
- pt -> Do("Func2");
- delete pt;
- }
void Func2()
{
Test* pt = new Test;
pt -> Do("Func2");
delete pt;
}
现在看看,是不是在两个函数返回时,都能够销毁对象。
现在你明白了吧?
由此,可以得出一个结论:指针只负责为对象分配和清理内存,并不与内存中的对象实例有直接关系。