针对类的成员变量,new/delete操作,constructor和destructor的调用顺序,在Linux下写了几个测试程序:
src file 1: AB.h
#include
<
iostream
>
using namespace std;
class A
{
public :
A()
{
cout << " Class A is newed " ;
}
~ A()
{
cout << " Class A is destroyed " ;
}
};
class B
{
public :
B()
{
cout << " Class B is newed " ;
}
~ B()
{
cout << " Class B is destroyed " ;
}
A a;
};
using namespace std;
class A
{
public :
A()
{
cout << " Class A is newed " ;
}
~ A()
{
cout << " Class A is destroyed " ;
}
};
class B
{
public :
B()
{
cout << " Class B is newed " ;
}
~ B()
{
cout << " Class B is destroyed " ;
}
A a;
};
src file 2 - AB.cc
#include
"
AB.h
"
int main()
{
B * bp = new B();
return 0 ;
}
int main()
{
B * bp = new B();
return 0 ;
}
输出(没有delete, 导致memory leak):
>
.
/
AB
Class A is newed
Class B is newed
Class A is newed
Class B is newed
src file 3 - AB.cc
#include
"
AB.h
"
int main()
{
B * bp = new B();
delete bp;
delete bp;
return 0 ;
}
int main()
{
B * bp = new B();
delete bp;
delete bp;
return 0 ;
}
输出(delete bp两次, 导致错误):
>
.
/
AB
Class A is newed
Class B is newed
Class B is destroyed
Class A is destroyed
Class B is destroyed
Class A is destroyed
*** glibc detected *** double free or corruption (fasttop): 0x0902f008 ***
Abort
Class A is newed
Class B is newed
Class B is destroyed
Class A is destroyed
Class B is destroyed
Class A is destroyed
*** glibc detected *** double free or corruption (fasttop): 0x0902f008 ***
Abort
src file 4 - AB.cc
#include
"
AB.h
"
int main()
{
B * bp = new B();
delete bp;
bp = NULL;
delete bp;
return 0 ;
}
int main()
{
B * bp = new B();
delete bp;
bp = NULL;
delete bp;
return 0 ;
}
正确,输出:
Class A
is
newed
Class B is newed
Class B is destroyed
Class A is destroyed
Class B is newed
Class B is destroyed
Class A is destroyed
src file 5 - AB.cc
#include
"
AB.h
"
int main()
{
B b[ 2 ];
return 0 ;
}
int main()
{
B b[ 2 ];
return 0 ;
}
输出:
>
.
/
AB
Class A is newed
Class B is newed
Class A is newed
Class B is newed
Class B is destroyed
Class A is destroyed
Class B is destroyed
Class A is destroyed
Class A is newed
Class B is newed
Class A is newed
Class B is newed
Class B is destroyed
Class A is destroyed
Class B is destroyed
Class A is destroyed
这个输出和下面的代码是一样的,但一个是类数组,一个是类指针
int
main()
{
B * bp = new B[ 2 ];
delete [] bp;
return 0 ;
}
{
B * bp = new B[ 2 ];
delete [] bp;
return 0 ;
}
直接定义的类变量,从stack里面分配内存,在函数结尾自动回收。new出来的对象是从heap中分配内存,要手动delete回收。
几点心得:
- 在调用class B的constructor之前,成员变量a已经初始化(已经被new出来了)
- 先调用class B的destructor之后,才去清理其它成员变量
- 可以delete一个NULL 的指针,因为delete操作实际上是这样的:
//
Original code: delete p;
if (p != NULL) {
p ->~ Fred();
operator delete(p);
}
if (p != NULL) {
p ->~ Fred();
operator delete(p);
}
- 不能对一个指针delete两次,否则会出现不可预知的后果(第二次)
- 最好的编程习惯:delete一个指针之后立即把它置成NULL:
delete bp;
bp = NULL;
---------
Linux 编译命令:
C++ source file:
g++ -o AB AB.cc
C source file:
gcc -o t1 t1.c