- 论坛徽章:
- 0
|
今天我想到了一个测试 GetPointer()->Method() 方法。
我现在怀疑的是在函数返回后栈空间会被系统回收,也就是说函数的返回值会被析构掉。因为这个指针是一个内置类型我们无法知道它有没有被析构。这样我就想到可以写一个类来代替那个内置的指针。以下是我写的测试代码,只列出于讨论有关的部分。
class AA
{
public:
void Method() { cout << "AA:Method() ~~~~" << endl; }
};
class AAPtr
{
public:
AAPtr(AA* pa);
AAPtr(const AAPtr& Other);
~AAPtr();
AA* operator -> () { return m_pa; }
private:
AA* m_pa;
size_t* m_pUse;
static const size_t LEN = 4;
char m_szFlag[LEN]; // 记录 AAPtr 对象是由构造函数生成还是由 copy 构造函数生成
};
AAPtr::AAPtr(AA* pa) : m_pa(pa), m_pUse(new size_t(1))
{
strncpy_s(m_szFlag, LEN, "con", LEN);
cout << "AAPtr's constructor: " << *m_pUse << endl;
}
AAPtr::AAPtr(const AAPtr& Other) : m_pa(Other.m_pa), m_pUse(Other.m_pUse)
{
++*m_pUse;
strncpy_s(m_szFlag, LEN, "cpy", LEN);
cout << "AAPtr's copy constructor:" << *m_pUse << endl;
}
AAPtr::~AAPtr()
{
cout << "AAPtr's destructor: " << m_szFlag << endl;
if (--*m_pUse == 0)
{
delete m_pa;
delete m_pUse;
}
}
AAPtr GetPointer()
{
AAPtr ap(new AA());
return ap; // 在这里会调用拷贝构造函数生成一个临时对象,然后 ap 会被析构
}
int main()
{
GetPointer()->Method();
cout << "-------------------------" << endl;
GetPointer();
cout << "-------------------------" << endl;
GetPointer(), cout << "***This is my conclusion!!!!!" << endl;
cout << "-------------------------" << endl;
return 0;
}
我在 AAPtr 的析构函数中插入了输出语句,这样就知道该对象有没有被析构。AAPtr 中还有一个成员变量 m_szFlag。该变量在对象被构造时会被设为 con (代表该对象是被构造生成的)。m_szFlag 在拷贝构造函数被设为 cpy (代表该对象是被拷贝生成的)。在 AAPtr 对象被析构时会输出 m_szFlag 的值。这样可以知道是哪种对象被析构了。
在看结果前先想一下结果。
如果说在 GetPointer() 返回后栈空间就没了,那么那个临时对象就会被析构掉。也就是说我们会看到两个析构函数的输出语句然后再才看到 Method() 内的输出。但结果不是这样的。以下是输出结果。
由输出顺序可以看到由构造生成的对象被析构了,但由拷贝生成的临时对象却在调用了Method() 后才被析构。
我得出一个结论,由函数返回值生成的对象并不是在函数返回后就被删除的,而是在一条语句结果后才结束的。不信再看看最后那两行输出结果。
以上是Visual Studio 8.0.50727.42输出结果。在gcc 4.3 中测试时没看到拷贝构造函数被调用,不知是否是被 gcc 优化了。但结论还是没变。
以上是我的理解,有什么问题大家说出来讨论一下。 |
|