class A
{
public:
A(){cout << "A" << endl;}
~A(){cout << "~A" << endl;}
};
void del(A *ptr)
{
delete ptr;
}
int main()
{
A *p = new A;
del(p);
return 0;
}
代码正常执行,delete p;先执行类析构函数,通知系统这块内存上的数据已经无效无需维护了,然后使用operator delete 释放这块内存
class A;
void del(A *ptr)
{
delete ptr;
}
class A
{
public:
A(){cout << "A" << endl;}
~A(){cout << "~A" << endl;}
};
int main()
{
A *p = new A;
del(p);
return 0;
}
vs2005:warning C4150: deletion of pointer to incomplete type 'A'; no destructor called
前向声明注意的地方,这个时候声明,承诺在文件的某个地方存在A的定义,但是对于函数del
的语句delete ptr;它编译的时候,看不到类A具体的情况,所以看不到析构函数的情况
这样它只释放内存,而并的未通知系统这块内存的数据已经无效,所以对于系统而言,它认为
这块内存上的数据仍是一个完整的对象,因为并无析构函数通知它
由此可见,编译,链接的过程
对于函数真正的功能执行,时存在顺序的,注意点
在iso,incomplete-type;
函数可以声明,链接的时候,指令代码块只存的一块,都去那里找,类型声明由于用在多个函数之中
所以每个函数链接的时候去找类型定义块,速度慢,而且不能马上的知道编译过程的错误,比如是否存在某个成员函数,这样情形需在编译的时候就能检测到,如果把查找类型的定义块的工作放在编译处,则速度非效率,
所以折中一点,定义放在使用处的前面,这样类定义块已经经过编译,在编译使用代码的时候,即可知道使用的正确与否个人的看法
{
public:
A(){cout << "A" << endl;}
~A(){cout << "~A" << endl;}
};
void del(A *ptr)
{
delete ptr;
}
int main()
{
A *p = new A;
del(p);
return 0;
}
代码正常执行,delete p;先执行类析构函数,通知系统这块内存上的数据已经无效无需维护了,然后使用operator delete 释放这块内存
class A;
void del(A *ptr)
{
delete ptr;
}
class A
{
public:
A(){cout << "A" << endl;}
~A(){cout << "~A" << endl;}
};
int main()
{
A *p = new A;
del(p);
return 0;
}
vs2005:warning C4150: deletion of pointer to incomplete type 'A'; no destructor called
前向声明注意的地方,这个时候声明,承诺在文件的某个地方存在A的定义,但是对于函数del
的语句delete ptr;它编译的时候,看不到类A具体的情况,所以看不到析构函数的情况
这样它只释放内存,而并的未通知系统这块内存的数据已经无效,所以对于系统而言,它认为
这块内存上的数据仍是一个完整的对象,因为并无析构函数通知它
由此可见,编译,链接的过程
对于函数真正的功能执行,时存在顺序的,注意点
在iso,incomplete-type;
函数可以声明,链接的时候,指令代码块只存的一块,都去那里找,类型声明由于用在多个函数之中
所以每个函数链接的时候去找类型定义块,速度慢,而且不能马上的知道编译过程的错误,比如是否存在某个成员函数,这样情形需在编译的时候就能检测到,如果把查找类型的定义块的工作放在编译处,则速度非效率,
所以折中一点,定义放在使用处的前面,这样类定义块已经经过编译,在编译使用代码的时候,即可知道使用的正确与否个人的看法