首页 > 编程语言 >C++CLI 析构函数和终结器理解

C++CLI 析构函数和终结器理解

时间:2024-02-04 22:44:09浏览次数:28  
标签:调用 Console 函数 WriteLine C++ 析构 Hello CLI

测试类:

#pragma once
ref class Hello
{
public:
    Hello();
   ~Hello();
   !Hello();
};


/***************/


#include "Hello.h"

Hello::Hello()
{
    System::Console::WriteLine("构造函数!");
}

Hello::~Hello()
{
    System::Console::WriteLine("析构函数!");
}

Hello::!Hello()
{
    System::Console::WriteLine("终结器:!");
}

主函数:

#include "Hello.h"

using namespace System;


int main()
{
    {
        Hello ^hello = gcnew Hello();
        delete hello; // 显示释放
    }

    {
        Hello h;  // 这种栈对象,超过作用域会调用析构函数。也是显式释放。
    }

    String^ info = Console::ReadLine();
    Console::WriteLine("信息:{0}", info);
    GC::Collect(); // 垃圾回收
    return 0;
}

上面的主函数,运行输出会这样:

构造函数!
析构函数!
构造函数!
析构函数!

如果,动态对象不显示释放:

int main()
{
    {
        Hello ^hello = gcnew Hello();
        //delete hello; // 不显示释放
    }

    {
        Hello h;  // 这种栈对象,超过作用域会调用析构函数。也是显式释放。
    }

    String^ info = Console::ReadLine();
    Console::WriteLine("信息:{0}", info);
    GC::Collect(); // 垃圾回收
    return 0;
}

输出应该这样:

构造函数!
构造函数!
析构函数!
终结器:!

经测试,Hello ^hello = gcnew Hello(); 这种动态对象,如果用 delete 显示释放,会调用析构函数。终结器是在GC回收前调用的;如果显示释放调用了析构函数,就不会再调用终结器了。所以要注意这个。 gcnew 动态调用,不显示释放,GC 回收的话会调用终结器。所以一般用下面这种方式,保证什么情况都能释放非托管内存:

Hello::~Hello()
{
    // 这里释放非托管资源 
    System::Console::WriteLine("析构函数!");
    !Hello();   // 在析构函数里再调用终结器
}

Hello::!Hello()
{
    //  这里释放非托管资源 
    System::Console::WriteLine("终结器:!");
}

标签:调用,Console,函数,WriteLine,C++,析构,Hello,CLI
From: https://www.cnblogs.com/huvjie/p/18007150

相关文章

  • C++ Primer 学习笔记 PartI C++基础
    Ch1开始略这一章包含控制流,条件,循环,注释,标准IO等内容。对于C语言/ACMC+STL中常见数值的内容不再赘述,仅总结较为不熟悉的内容。PartIC++基础CH2变量和基本类型2.1基本内置类型2.1.1算术类型2.1.1类型转换向unsigned赋超出范围的值,结果取余,对于signed,结果未定义。......
  • CF235C Cyclical Quest
    更好的阅读体验CF235CCyclicalQuestSAM做法:对于主串建SAM,然后parenttree上DP出\(f_i\)表示节点\(i\)后缀等价类的出现次数。询问先用KMP求最小循环元\(m\),然后接下来需要把\([1,n],[2,n]\dots[m-1,n+m-1]\)扔进SAM里跑。暴力显然过不去,但是跑完一次可以删......
  • C++中promise和future初认识
    future/promisefuture提供了一个基于数据(future模板类型)的异步概念:对于一个类型T,可以在以后通过get接口获得这个类型T的变量。或者打个不太恰当的比方,当你获得一个future对象时,就获得了一个消费券(consumer):拿着这张券可以兑换(get)一个T类型的结果(如果数据未就绪的话会阻塞等......
  • 通信工具类countdownlatch和cyclicbarrier
    类作用semaphore限制线程数量exchanger两个线程交换数据countdownlatch递减屏障,线程等待直到计数器减为0时开始工作cyclicbarrier循环屏障,等屏障的线程数达到初始化值时,执行自定义的任务phaser增强的cyclicbarriercountdownlatch和cyclicbarrier区......
  • C++多线程 第三章 在线程间共享数据
    第三章在线程间共享数据共享数据基本问题如果所有共享数据都只读,那就没有问题.不变量(invariants):对特定数据结构总为真的语句.例如:"该变量表示线程数量."修改线程之间共享数据的一个常见潜在问题就是破坏不变量.竞争条件(racecondition):线程竞争执行各自的操作,导......
  • C++之INI配置文件读写/注释库 inicpp 介绍【简单易用-包含inicpp.hpp头文件即可】
    一个头文件(header-file-only)搞定INI文件读写、甚至进行注释。跨平台,并且用法极其简单。MITlicense,从此配置INI文件就像喝水。【注:对您有帮助的话,Star或Issues为项目维护提供动力,感谢。】-byofficalofJN-inicppproject.一、库下载https://github.com/dujingning/inicpp......
  • DotNetty 封装的TcpClient
    .net里 Netty资料不多,做个记录publicclassNetworkCommunicator:ICommunicator{#regionNetty本来想用静态,后来觉得多个client公用一个netty可能分不清返回的数据,先这样,后期要是吃资源再优化Bootstrap_NettyBoot;IEventLoopGroup_NettyEventLoop;......
  • DotNetty 封装的 UdpClient
    DotNetty资料较少,UdpClient和TcpClient略有不同publicclassUdpCommunicator:ICommunicator{privateIChannel?_ClientChannel;privateBootstrap?_Bootstrap;IEventLoopGroup?_LoopGroup;privateTaskCompletionSource<byte[]>_ResponseComp......
  • 14. C++函数的编译
    C++函数的编译C++和C语言的编译方式不同。C语言中的函数在编译时名字不变,或者只是简单的加一个下划线_(不同的编译器有不同的实现),例如,func()编译后为func()或_func()。而C++中的函数在编译时会根据它所在的命名空间、它所属的类、以及它的参数列表(也叫参数签名)等信息进行重新......
  • 创建大量栅格文件并分别写入像元数据:C++ GDAL代码实现
      本文介绍基于C++语言GDAL库,批量创建大量栅格遥感影像文件,并将数据批量写入其中的方法。  首先,我们来明确一下本文所需实现的需求。已知我们对大量遥感影像进行了批量读取与数据处理操作——具体过程可以参考文章C++GDAL提取多时相遥感影像中像素随时间变化的数值数组;而随......