auto_ptr问题
---------------------------------------------------
head.h:
#include <memory>
class X{
public:
class Y{};
std::auto_ptr<Y> py;
};
---------------------------------------------------
a.cpp:
#include "head.h"
int main(int argc, char *argv[]){
X x;
return 0;
}
---------------------------------------------------
b.cpp(此时就相当为空,仅仅#include一个头文件而已):
#include "head.h"
---------------------------------------------------
此时编译成功。
现在作修改,将head.h中class Y的定义转移到b.cpp中:
---------------------------------------------------
head.h:
#include <memory>
class X{
public:
class Y;
std::auto_ptr<Y> py;
};
---------------------------------------------------
a.cpp:
#include "head.h"
int main(int argc, char *argv[]){
X x;
return 0;
}
---------------------------------------------------
b.cpp(此时就相当为空,仅仅#include一个头文件而已):
#include "head.h"
class X::Y{
};
---------------------------------------------------
此时编译就有问题了:在vs中是一个警告,而在g++中则是error。
大家不要错误地认为是由于“std::auto_ptr<Y> py;需要class Y的定义”而导致的错误(可能在vc6中是这么要求的,但是标准并没有这方面的强制要求)。这其实是more exceptional c++ 条款30,185页的一个问题,结合书上的解释,我的理解是:因为在a.cpp的main函数中有“X x;”,所以在main函数的结尾编译器会自动安插一个“x.~x();”(即调用x对象的析构函数),而编译器为class X自动合成的析构函数中肯定会有类似“py.~auto_ptr<Y>();”之类的语句来调用数据成员的析构函数,并且由于编译器为class X自动合成的析构函数很小,所以编译器会将它设置为inline,这样一来“py.~auto_ptr<Y>();”就出现在main函数中了,这也就要求在a.cpp中将会有auto_ptr<Y>::~auto_ptr<Y>的实例化点,而在auto_ptr<Y>::~auto_ptr<Y>的实例化点肯定需要用到class Y的定义,但是在a.cpp中没有class Y的定义,所以出现错误。
more exceptional c++中提供的解决方案(当然不是“在头文件中提供class Y的定义”了)是(185页):如果你不想提供Y的定义,就必须显式地写出X的析构函数,即使函数体为空。
但是这个方法并不好用,即使显式提供X的析构函数,编译仍然有问题(你可以试一试)。后来我想了一下,就算我们显式提供了X的析构函数,编译器仍然会在析构函数体中安插“调用数据成员析构函数”的代码,即X的析构函数中仍然会存在类似“py.~auto_ptr<Y>();”之类的语句,所以问题依然存在。
不知道我分析得对不对,望高手指教。