当前位置:七道奇文章资讯编程技术VC/C++编程
日期:2011-03-22 13:55:00  来源:本站整理

若何删除托管对象及包装一个库[VC/C++编程]

赞助商链接



  本文“若何删除托管对象及包装一个库[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

在托管 C++ 中,请奉告我利用 delete 操作符销毁托管对象能否安全?

是的,在托管 C++ 中,你可以删除( delete )托管对象,只要你理解删除只不过是调用对象的析构函数,但析构函数必须显示定义.调用 delete 不会释放对象的存储区.只有垃圾汇集器才行.Figure 1 展示了一个简单的程序,该程序定义了一个带析构函数的托管类,当它运行的时刻会显示一条信息.TESTDTOR 分配两个 ManagedClass 实例.它显式删除第一个实例,但第二个则不然.假如运行 TESTDTOR,你会得到象下面这样的后果:

Begin main
ManagedClass(04A712D4)::ctor
ManagedClass(04A712D4)::dtor
ManagedClass(04A712E0)::ctor
End main
ManagedClass(04A712E0)::dtor
  它阐明了当 delete 语句履行时,第一个对象的析构函数当即履行;而第二个对象(at 04A712E0)则没有被销毁,直到掌握脱离 main 并且系统终止代码调用垃圾汇集器释放逗留对象.

Figure 2 Testdtor 的精彩输出

不管什么时刻,假如你不能肯定 .NET 环境中发生了什么,你老是可以编写一些代码,编译它并查抄微软中间语言(MSIL)产生的东西.正如 Figure 2 所展示的,定义析构函数招致编译器产生两个办法:一个是 Finalize 办法,它包含你的实现(这里是调用 printf),一个是 __dtor 办法,它调用 System.GC::SuppressFinalize,然后再调用 Finalize.当你删除对象时,编译器产生一个对此 __dtor 办法的掉用.假如你用 /FAs 编译 TESTDTOR 来产生有源码的程序集清单,你将看到 delete 语句以以下的方法编译:
; delete pmc;
ldloc.0 ; _pmc$
call ??1ManagedClass@@$$FQ$AAM@XZ
  奇特奥秘的标记是被修饰过的析构函数(__dtor).

纯熟的 C++ 程序员大概会弄不懂得,假如调用 delete 都无法释放对象,那调用它有干什么?好问题.调用 delete 的唯一来由是收回任何你的类所利用的非托管资源.比方,假如你的对象翻开数个文件或成立了数据库衔接,你可以写一个关闭其资源的析构函数,然后在用完该对象时利用 delete 释放它.在托管类中释放资源的一个更好的办法是通过实现 Dispose 情势,IDisposable——假如你在写托管 C++ 代码——由 auto_dispose 来调用它.(更多的信息拜见 Tomas Restrepo 在 MSDN 杂志 2002 仲春刊上的文章:“Tips and Tricks to Bolster Your Managed C++ Code in Visual Studio .NET”).

假如你实现 dispose 情势,其他的 .NET 利用者也可以利用它.假如你自己在析构函数中举行清理,别的语言便没有办法显式调用你的清理代码.因为在 C# 和 Visual Basic 中没有 delete 操作符.

所今后果是你能调用 delete 来触发你的析构函数,但是将清理代码放在析构函数中大概不是一个好主张.最好是实现 IDisposable,这样全部人都能利用.注意,在 Visual C++ 2005 中,这个行为有所改变.更多信息拜见 Andy Rich 对这个问题的谈论:“Deterministic Finalization IV - Benefits, part II”,以及当前的 C++/CLI 语言标准尺度:“C++/CLI Language Specification Standard”

我有一个返回链表的非托管函数,此中有 char* 字符串:

struct blah {
  int a, b;
  char *a, *b;
  struct blah *next;
};
struct blah *getmystruct();
  因为 getmystruct() 分配内存,当用完之后,我需求调用 freemystruct(struct blah *b).我尝试做一个包装器,用它来将之转换成托管范例的调集,但我不知道当需求释放全部这些指针的时刻,该若何来处理.你可否赐教?

为什么,的确.你不能用 dllimport 语句将你的本地链表转换成托管范例调集.interop 服务当然不错,但处理此问题也不是那么好!你需求编写一个包装器,显式地将你的链表转换为托管调集,象 ArrayList.我写了一个带有三个模块的程序,ListWrap,它示范了具体做法.第一个模块,ListLib.cpp,实现一个本地 C++ 库(DLL),此中有两个函数,AllocateList 和 FreeList.辨别用来分配和释放本地 C++ 构造链表.它们模拟你程序中的 getmystruct 和 freemystruct 函数.第二个模块是一个托管 C++ 文件,ListWrap.cpp,它实现托管类 ManagedNode,该类包装本地 C++ 实现(拜见 Figure 3).第三个模块是 C# 测试程序,它调用包装器来展示它若何工作.详情请下载源代码.

ListLib.cpp 实现两个本地函数,AllocateList 和 FreeList,这两个函数用来分配和释放 NativeNode 构造链表:

// from ListLib.h
struct NativeNode {
  int a, b;
  TCHAR *str;
  struct NativeNode *next;
};
  ListWrap.cpp 中的包装器类 ManagedNode 模拟用 NativeNode 的定义,只是有两个小差别:本地 char* 被用托管的 String 替换,此外它没有 next 指针,因为我将用 ArrayList 实现链表构造.代码以下:
// managed equivalent of NativeNode
public __gc class ManagedNode {
public:
int a, b;
String* str;
};
  有了 ManagedNode 的定义,下一步是编写代码将 NativeNodes 转换到 ManagedNodes.但在开始之前,先停下来考虑一下转换函数应当是什么模样,他应当有什么样的参数,返回什么值.一种办法是编写一个函数,参数是本地 NativeNodes 链表并返回托管的 ManagedNodes 链表,在这个历程中大概销毁本地链表..NET 客户端利用程序将直接调用 ListLib DLL (或你的 getmystruct )以获得本地链表,将它作为 IntPtr 范例.然后,将这个 IntPtr 传送给转换函数,象下面这样:

// call DLL directly through interop
IntPtr nativeList = AllocateList(7);
// call wrapper to convert
ArrayList amanagedList = ListWrap.Convert(nativeList);
  大大都情形下,客户端将负责调用该 DLL 来释放本地链表,大概 Convert 函数自动完成.

一种差别的办法是通过在某个包装器中包装分配链表的本地函数 AllocateList 来完好躲藏这个 DLL,转换并在作为 ArrayList 返回托管链表之前释放本来的本地链表.哪类办法更好的呢?第一种战略的长处是你只需求编写单一的转换函数,它便可以在任何有本地链表的地方利用.第二个办法需求对每个成立链表的函数举行包装.假若有多个成立链表的函数,则工作量稍大一些.但是其长处是它向 .NET 客户端完好躲藏了全部的本地处理逻辑和细节.客户端不再需求去处理 IntPtrs 或乃至是导入此 DLL,因为 ListWrap 躲藏了一切.这是我将要采取的办法,同时也是我鼓舞你在自己的程序中利用的办法.固然对库举行完好的包装需求更多的勤奋,但是后果却越发坚固和完好的封装.
  有了 ManagedNode,剩下的事情就是包装 AllocateList.这个历程非常简单直白.首先,调用 AllocateList 分配本地链表,然后成立一个空的 ArrayList,接着将全部 NativeNodes 拷贝到 ManagedNodes 并将它们增添到托管链表中,最有脱离时删除它们.Figure 3 展示了全部的细节.托管 C++ 的美好之处在于即就是在处理混合对象时,全部的代码看起来都很俭朴文雅.将本地 char* 拷贝到托管 String 用一个赋值便可,就像下面这行代码:

mn->str = nn->str; // String = char*: it just works!
  不需求调用转换函数;编译器知道该怎么做.脱离 CreateList 时删除本地节点.这样做比在末尾删除它们存储更有效.


  以上是“若何删除托管对象及包装一个库[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • Windows 7中若何删除病毒文件夹
  • 若何删除Windows中不让删除的文件
  • 什么是Windows服务 若何删除windows服务
  • sql若何删除部份字段反复的数据
  • Win7和XP双系统若何删除GRUB
  • 若何删除windows.old文件夹
  • 若何删除托管对象及包装一个库
  • <b>Sql server中若何删除有默许值的列</b>
  • <b>Oracle10gR2若何删除误增添的空文件-开辟技术</b>
  • 若何删除过量的本地衔接2
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .