用户名: 密   码:
   飞诺网 加入收藏
飞诺网 软件编程 C C++ Java VB Delphi Foxpro 汇编语言 游戏开发 移动开发 软件工程师 软工与管理 VC shell编程 C#
C++系列教程 C++实例 C++技术文档 C++/C语言函数 Mangos

您当前的位置:飞诺网 >> c/c++ >> C++实例

ref类对象是分配在托管堆上的么?

www.diybl.com    时间 : 2008-08-03  作者:佚名   编辑:本站 点击:   [ 评论 ]

 今天看网上一片文章强调(出处忘记了),ref类对象的实例,是分配在托管堆上的仍然会被GC。我觉得很别扭,看《pro vc++ cli and .net 2.0 platform》的时候,有一个例子和网上说的十分相似,代码如下:

ref class RefClass {};

RefClass^ ERRORexample()
{
    RefClass a;
    // do some stuff;
    return %a;   

作者认为返回局部对象a的引用是无效的,这一点和传统C++返回局部对象的指针一样,将造成内存泄露;这样理解是比较清楚的,但是根据网上那篇文章的观点,认为实际上ref类对象也是分配在托管堆上的,并将被GC回收。文章还举了一个和上面程序一样的例子,经我在2005下运行的结果,的确只有警告,但是程序正确的被运行了。

那么,ref类对象究竟是分配在托管堆上的还是栈上的呢?

我写了以下程序,来尝试求证这个问题:

using namespace System;

ref class RefClass
{
    public:
     int _x;

     RefClass(int x):_x(x)
     {
     }

     RefClass(const RefClass% other)
     {
          _x = other._x;
          Console::WriteLine("copying");
     }   

     ~RefClass()
     {
          Console::WriteLine("died");
     }
};

 

RefClass% foo()
{
    RefClass a(10);

    return a;
}

RefClass^ foo2()
{
    RefClass^ a = gcnew RefClass(11);

    return a;
}

int main(array<System::String ^> ^args)
{
     RefClass r = foo();

    Console::WriteLine(r._x);

    RefClass^ r2 = foo2();

    Console::WriteLine(r2->_x);

    return 0;
}

结果程序运行的结果是:

died                                               这行表明foo中return a之后,局部对象被析构了
copying                                        这是拷贝构造函数得到了执行
10
11                                                 通过gcnew创建的对象句柄,并没有因为函数的结束被析构
died                                              最终程序结束时,给GC销毁

由此可见

ref类对象,也应该理解为分配在栈上的。

理由:

1 因其在函数结束时,被立即析构了

2 根据《pro vc++ cli and .net 2.0 platform》的提示,不应该把局部的ref类对象的引用作为函数返回值

唯一的疑惑:

vs 2005居然默许了前一个例子的运行,而只是给出警告,运行却是正确的。

 

如果图片或页面不能正常显示请点击这里
C++实例推荐文章

文章评论