【VC++】虚函数 内存结构 - 第一篇(单类)

c++类大小(涵盖继承 虚继承 虚函数表) 涉及到c++中求类大小时需要特别注意一下几点 1.为类的非静态成员数据的类型大小之和. 2.有编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针、虚继承、多重继承). 3.为了优化存取效率,进行的边缘调整. 4.  与类中的构造函数,析构函数以及其他的成员函数无关.  5.  私有继承,会去继承之前的私有成员变量么? 会...在内存中仍然分配 阅读详情

前言 - 为何写此系列文章?

网上讨论虚函数内存结构的文章很少,好不容易有几位大神写了几篇很精彩的文章,结果里面还有错误:

陈皓大神的《C++ 虚函数表解析》:
https://blog.youkuaiyun.com/haoel/article/details/1948051
《C++ 对象的内存布局(上)》:
https://blog.youkuaiyun.com/haoel/article/details/3081328
《C++ 对象的内存布局(下)》:
https://blog.youkuaiyun.com/haoel/article/details/3081385

在这里插入图片描述
还有位大神的《图说C++对象模型:对象内存布局详解》:
https://www.cnblogs.com/QG-whz/p/4909359.html
同样有错误。

但是,不否认,几位大神的文章写得确实精彩,我看了之后也受益匪浅,再次感谢几位大神的分享精神。
我并不是做C++的技术极客,几位大神的经验和水平肯定也会比我高,所以我写的此系列文章,重在研究探索与实践,难免有错误的地方,恳请大家大力吐槽,并恳求给出具体的解决方法,在此先谢过。会不定期更新,并记录提出修正方案的朋友,以示感谢,以帮助到更多的人。

前言 - 适合什么样的读者?

引用《深度探索C++对象模型》这本书中的话,有两个概念可以解释C++对象模型:
1、语言中直接支持面向对象程序设计的部分。
2、对于各种支持的底层实现机制。

直接支持面向对象程序设计,包括了构造函数、析构函数、多态、虚函数等等,这些内容在很多书籍上都有讨论,也是C++最被人熟知的地方(特性)。而对象模型的底层实现机制却是很少有书籍讨论的。对象模型的底层实现机制并未标准化,不同的编译器有一定的自由来设计对象模型的实现细节。在我看来,对象模型研究的是对象在存储上的空间与时间上的更优,并对C++面向对象技术加以支持,如以虚指针、虚表机制支持多态特性。

文章主要来讨论C++对象在内存中的布局,属于第二个概念的研究范畴。故读者需要有一定的C++面向对象基础、内存相关知识,比如内存对齐,指针操作等。看完之后,对C++虚函数会有一个底层的理解,可以解决工作中的一些实际问题,比如解决一些很迷惑的bug、逆向工程……

【VC++】虚函数 内存结构 - 第一篇(单类)

#include <IOSTREAM>
using namespace std;

class Base
{
public:
	int nBase1;
	int nBase2;

	Base(int n1,int n2):nBase1(n1),nBase2(n2)
	{
		cout<<"Base::Base("<<n1<<","<<n2<<")"<<endl;
	}

	virtual void F()
	{
		cout<<"Base::F()"<<endl;
	}
	virtual void G()
	{
		cout<<"Base::G()"<<endl;
	}
};


typedef void(*Fun)(void);	

void TestBase(Base &b)
{
	Fun pFun = NULL;

	cout << "类对象地址 / 虚函数表指针的地址:" << (&b) << " / " <<    (int*)(&b)+0 << endl;//虽然两个地址值一样,但前者是类对象的地址,后者是对象里面的首地址。好比字符串的地址,和字符串里第一个字符的地址,是一样的。
	cout << "虚函数表指针值(虚函数表的地址)(十进制):"	<<        *(int*)(&b) <<endl; //就省略+0了(就是首地址偏移0,还是首地址)
	cout << "虚函数表指针值(虚函数表的地址)(十六进制):" << (int*)*(int*)(&b) <<endl; //显式指针转换,告知是个指针,输出就是十六进制了
	cout << "虚函数表 — 第 1 个函数地址的地址:"  <<		    (int*)*(int*)(&b) << " , ";	 //好比一个变量的地址
					   cout << "函数地址值:"<<			 (int*)*(int*)*(int*)(&b) << " 调:";//好比一个变量的值(这个值也是个地址)
	pFun = (Fun)*(int*)*(int*)(&b);//(Fun)(int*)*(int*)*(int*)(&b)的简化,上行代码最左边的(int*)是显式指针转换,可直接替换成(Fun)
	pFun();
	
	cout << "虚函数表 — 第 2 个函数地址的地址:"  <<		    (int*)*(int*)(&b)+1 << " , ";
					   cout << "函数地址值:"<<		    (int*)*((int*)*(int*)(&b)+1) << " 调:";
	pFun = (Fun)*((int*)*(int*)(&b)+1);
	pFun();

	cout << "虚函数表 — 第 3 个函数地址的地址:"  <<		    (int*)*(int*)(&b)+2 << " , ";
					   cout << "函数地址值:"<<		    (int*)*((int*)*(int*)(&b)+2)<<endl;	//如果仅有一个虚函数,后面的节点不是NULL???
	
	cout << "类对象 — 第 1 个变量地址:" << ((int*)(&b)+1)  << " 值:"<< *((int*)(&b)+1) <<endl;	
	cout << "类对象 — 第 2 个变量地址:" << ((int*)(&b)+2)  << " 值:"<< *((int*)(&b)+2) <<endl;
	cout << "类对象 — 第 3 个变量地址:" << ((int*)(&b)+3)  << " 值:"<< *((int*)(&b)+3) <<endl;	//之后的内存是什么???
	
	cout<<endl;
}

void TestBase2(Base &b)
{
	Fun pFun = NULL;
	int** pVtab = (int**)&b;
	
	cout << "类对象地址 / 虚函数表指针的地址:" << (&b) << " / " << pVtab << endl;
	cout << "虚函数表指针值(虚函数表的地址)(十进制):" << (int)pVtab[0] <<endl;
	cout << "虚函数表指针值(虚函数表的地址)(十六进制):" << pVtab[0] <<endl; 

	cout << "虚函数表 — 第 1 个函数地址的地址:"  <<  &pVtab[0][0] << " , ";	//好比一个变量的地址
					   cout << "函数地址值:"  << (int*)pVtab[0][0] << " 调:";	//好比一个变量的值(这个值也是个地址)
	pFun = (Fun)pVtab[0][0];
	pFun();

	cout << "虚函数表 — 第 2 个函数地址的地址:"  <<  &pVtab[0][1] << " , ";
					   cout << "函数地址值:"  << (int*)pVtab[0][1] << " 调:";
	pFun = (Fun)pVtab[0][1];
	pFun();

	cout << "虚函数表 — 第 3 个函数地址的地址:"  <<  &pVtab[0][2] << " , ";
					   cout << "函数地址值:"  << (int*)pVtab[0][2] <<endl ;	//如果仅有一个虚函数,后面的节点不是NULL???
	//pFun = (Fun)pVtab[0][2];
	//pFun();
	
	cout << "类对象 — 第 1 个变量地址:" << &pVtab[1]  << " 值:"<< (int)pVtab[1] <<endl;	
	cout << "类对象 — 第 2 个变量地址:" << &pVtab[2]  << " 值:"<< (int)pVtab[2] <<endl;
	cout << "类对象 — 第 3 个变量地址:" << &pVtab[3]  << " 值:"<< (int)pVtab[3] <<endl;	//之后的内存是什么???
	
	cout<<endl;
}

void main()
{
	Base b1(123,321);
	Base b2(456,654);

	cout<<"------------------------- 法一:地址偏移"<<endl;
	TestBase(b1);
	TestBase(b2);
	cout<<"------------------------- 法二:二维指针"<<endl;
	TestBase2(b2);
	
	cout<<endl;
}

运行结果:
在这里插入图片描述
比对看三种Test(红色表示不同的地方):
同一个类,两个不同的对象 比较:
在这里插入图片描述

同一个类对象,两种不同的方法 比较:
在这里插入图片描述

在内存中的结构是:
在这里插入图片描述
上图中,类对象b1的首地址 0019FF24,是类对象b2末尾紧接的地址 0019FF24,此例b2和b1在内存空间里是连续分布的,但并不是同一类的所有对象,在内存空间里都是连续分布的,而是取决于栈上的顺序。本例中,b1先入栈,紧接着b2入栈,栈的增长方向是往低地址增长,故b2在低地址,往高地址紧接着就是b1。因为定义顺序是紧挨着的,如果中间插入定义了其它局部变量,b2和b1就不连续。若有兴趣详细研究,可以看这篇文章:
《变量在内存里的存储区域》:https://blog.youkuaiyun.com/maoyeahcom/article/details/108940270

在本文结束前,我也还是来介绍下自己吧。我从03年初学编程,一直到现在都在做软件开发方面的事,做过VC++、VB/Delphi/C++Builder、C#/Asp.Net、Java、Web前后端、数据库、服务器端、客户端、js、lua、Flash AS、cocos2dx/Unity3d……都有接触过,甚至做过很长一段时间的运营、产品策划、美工、客服、线下推广员、公司经理 多职务……技术只是一种工具,用来实现业务需求,所以最大的特长是逻辑思维、挖掘业务需求、强化用户体验、快速的产品实现,最自以为豪的,我做过的很多产品,很稳定,bug极少(当然也出现过没考虑周全的漏洞在所难免但总体上也还算少),有很多独立开发的游戏运营到现在还在稳定的运行。不是技术极客,而是业务需求带动技术的学习研究,所以也不怎么挑语言,编程语言大体上也都是相通的,底层原理也有很多类同的地方。所以缺点从不敢说精通哪一门语言。遇到小工具、小需求的订制实现,我个人最喜欢的还是用VC6,简洁干净,编译出来的东西 体积小,速度快,占CPU内存小。当然实际工作中,还是随项目。欢迎大家和我交流,我的QQ是:七6.肆-陆_柒-4`7_四.
生活中的我,热爱 街舞、飙车、花式游泳、游戏一条命通关……极限运动,我抖音号(一不小心玩出花样)是:1917940952

文章没有考虑字节对齐(都用默认的字节对齐),并且是在32位环境下,VC6、VS2017 都测试过。

	//文章没有考虑字节对齐(都用默认的字节对齐),并且是在32位环境下
	cout<<"sizeof(Base): "<<sizeof(Base)<<endl;	//输出值:12(4*3) 两个int各占4字节,32位指针占4字节

在这里插入图片描述

安全性

C++有很多搬石头砸自己脚的东西,比如const修饰就是想不被更改,但又有个const_cast来破坏这种约定。同样的,对于类成员变量、虚函数,用non-public(比如private或是protected)修饰,就是一种限制约定(比如不能直接 对象. 来访问),外部访问时编译器会报错,但通过本文的方法(下面的代码示例),可以绕过编译器检查,在运行时又能正常的访问。水可载舟,亦可覆舟。重在清楚原理,然后视场景情况而运用。

#include <IOSTREAM>
using namespace std;

class Base 
{
//public:
private:	
	virtual void F() 
	{ 
		cout << "Base::F()" << endl; 
	}	
};

typedef void(*Fun)(void);

void main() 
{	
    Base b;	
	//b.F();//访问private修饰的,会报错
    Fun  pFun = (Fun)*(int*)*(int*)(&b);	
    pFun();	
}

再来看看下面这个代码:

#include <IOSTREAM>
using namespace std;

class Base 
{
public:	
	int nBase;
	virtual void F() 
	{ 
		nBase = 123;
		cout << "Base::F()" << endl; 
	}	
};

typedef void(*Fun)(void);

void main() 
{	
    Base b;	
	b.nBase = 0;

	//b.F();	//执行后,nBase值改变了

    Fun  pFun = (Fun)*(int*)*(int*)(&b);	
    pFun();	

	cout<<"b.nBase : "<<b.nBase<<endl<<endl;
}

在 F() 加入了对成员变量的访问,一般用法 b.F(),能正常访问,但用本文的方法,会出错:
在这里插入图片描述
这又是为什么?因为 成员变量 nBase是类对象的,b.F()访问时,会正常传入类对象的this指针,也就能正常访问nBase。但用本文的方法访问 F(),把它当成一种普通的函数,解析this指针地址是F()的函数地址,从这个地址开始的内存块 被解析成一个Base对象……想象一下多乱,导致非法访问。
再延伸 再刨根,有无穷无尽的东西要研究,偏离本文的主题,有兴趣的童鞋可以再去研究。

(转载时请注明作者和出处。未经许可,请勿用于商业用途)
原创出处:https://blog.youkuaiyun.com/maoyeahcom/article/details/108728608

C/C++面试题2「虚函数、多态、内存管理与软件调试篇」 C/C++面试题分享「虚函数、多态、内存管理与软件调试篇」 阅读详情

相关推荐

Cesium生态盘点:超图、火星3D等15个二次开发框架对比

本文深入解析Cesium生态中的15个二次开发框架,包括超图、火星3D等主流选择,帮助开发者根据项目需求进行精准选型。从性能表现、功能完备性、开发友好度等维度进行对比,特别适合需要处理地理空间数据和构建三维可视化的JavaScript开发者。

weixin_28197941的博客 497

【C++ | 虚函数】虚函数详解 及 例子代码演示(包含虚函数使用、动态绑定、虚函数表、虚表指针)

👉本文介绍了C++的虚函数,包括虚函数的定义、重写,动态绑定、虚函数表、虚表指针等内容。

wkd_007的博客 7098

解锁Jetbrains AI助手:中国开发者实战配置与效率跃迁指南

本文为中国开发者提供了一份详细的Jetbrains AI助手实战配置指南。针对服务地域限制,核心解决方案是通过修改Jetbrains账户区域信息并配置网络代理,实现插件的稳定启用。文章进一步分享了AI助手在解读遗留代码、生成中文提交信息、智能问答等场景下的具体应用,旨在帮助开发者深度集成这一工具,实现编码生产力的显著提升。

weixin_28832121的博客 576

VC++入门经典学习笔记--虚函数

1.引入虚函数继承的成员函数的行为以及他们与派生类成员函数的关系。给CBox类添加一个输出CBox对象体积的函数。1.新建win32控制台项目项目,右键添加新建项CBox.h类:#pragma once #include <iostream>using std::cout; using std::endl; class CBox { public: //输出箱子体积函数 void s

freshstraw的博客 963

手把手教你用Ubuntu 22.04的附加驱动工具安装NVIDIA显卡驱动(含常见错误修复)

本文详细介绍了在Ubuntu 22.04系统上,如何通过图形化的“附加驱动”工具安全、便捷地安装NVIDIA显卡驱动。内容涵盖从准备工作、禁用默认的nouveau驱动、图形界面安装实操,到安装后的验证(如使用nvidia-smi命令),并提供了安装失败黑屏、亮度调节失效等常见问题的深度解决方案,帮助用户彻底搞定驱动安装难题。

weixin_29248653的博客 602

面向精准医疗的多模态影像融合:实现前列腺MRI与大病理切片的三维配准与空间重建研究

亲爱的同学,当你能完整实现“前列腺MRI与大病理组织学图像的3D配准及体素重建”,你会发现医学影像交叉领域的毕设课题充满挑战与乐趣。我们将从临床需求出发,拆解3D配准与体素重建的核心技术,带你从原理到代码实现完整流程,让你的毕设不仅能顺利完成,更能体现临床应用价值。,让MRI和病理图像在同一空间对齐,能实现“术前影像-术后病理”的精准关联,为前列腺癌的精准诊疗、预后评估提供关键依据——这一课题既有技术挑战性,又有临床意义,是毕设的优质选择。(如NCC、Dice、配准时间),用数据证明方法的优越性。

m0_71589036的博客 4717

C++虚函数

C++虚函数: 仅在定义父类成员函数的函数原型前加关键字virtual,子类如果重写了父类的虚函数那么子类前的virtual 关键字可写可不写,但是为了代码具有可读性,最好还是加上virtual关键字。 子类重写父类虚函数的条件: 子类的函数名称与父类的虚函数名称相同,参数列表也要相同,返回值也相同(如果返回的是子类类型的指针或 者引用也可以),调用约定也相同...

weixin_30791095的博客 207

Python之achatbot包语法、参数和实际应用案例

本书是一本PyTorch深度学习实战指南,分为基础(前6章)和进阶(后5章)两大部分。基础部分涵盖张量运算、神经网络、数据预处理及CNN等核心内容;进阶部分则深入图像、文本、音频建模技术,重点解析Transformer架构及大语言模型开发。全书采用"理论+实践"模式,适合从零基础到进阶的PyTorch学习者。

王国平的博客 632

C++ 虚函数 (virtual function)

C++ 虚函数 (virtual function). 虚拟函数是什么, 虚拟函数的使用方法.

我是小白呀的博客 8678

YOLO26涨点改进 | 全网独家,注意力创新改进篇 | Arxiv2025 | YOLO26引入MSLA多尺度线性注意力模块,高效提取多尺度特征和建模长程依赖,含多种创新改进,助力有效涨点

本文提出了一种多尺度线性注意力模块(MSLA)来优化YOLO26模型。MSLA通过并行使用不同尺寸的深度可分离卷积(3×3至9×9)提取多尺度特征,并结合线性注意力机制高效建模全局依赖关系。该模块显著提升了模型对多尺度目标的检测能力,同时保持了轻量化特性。实验表明,MSLA能有效增强小目标检测和复杂场景下的分割精度。文章详细介绍了MSLA的网络结构、核心优势及实现代码,并提供了两种集成MSLA的YOLO26改进方案,为实时目标检测任务提供了高效解决方案。

Ai缝合怪、助力小伙伴高效发论文 298

深入YOLOv8内部核心:用RepNCSPELAN4深度重构主干网络,即插即用的高效涨点方案

本文提出了一种改进YOLOv8目标检测模型的方法,通过在YOLOv8中引入RepNCSPELAN模块来提高检测性能。该模块融合了RepVGG重参数化思想与CSP-ELAN结构,在保持推理速度的同时增强特征表达能力。实验结果表明,改进后的RepNCSPELAN-YOLOv8相比原模型在多项指标上均有提升:准确率从0.84提高到0.86,召回率从0.72提升至0.81,mAP50和mAP50-95也分别提高了0.06和0.04。文章详细介绍了模块设计原理和移植步骤,包括配置文件创建、代码修改等关键环节,为YOL

FJN110的博客 187

C++ 虚函数详解

前言 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。 关于虚函数的使用方法,我在这里不...

smartDMer的专栏 7871

电压跟随器在ADC采样电路中的作用分析

电压跟随器在ADC采集系统中扮演关键角色,它能解决分压电路因ADC输入阻抗导致的电压误差问题。通过运放构成的电压跟随器可隔离信号源与负载,保证采样精度,尤其适用于高阻抗传感器或高速采样场景。工程应用中需注意运放带宽、轨对轨输出能力及抗干扰设计。合理使用电压跟随器能显著提升信号完整性,在复杂电子系统中成为不可或缺的"信号桥梁。

硬核科技 658

【VC++】虚函数 内存结构 - 第四篇(多重继承,无虚函数覆盖)

【VC++】虚函数 内存结构 - 第四篇(多重继承,无虚函数覆盖)

maoyeahcom的博客 266

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【VC++】虚函数 内存结构 - 第二篇(单继承,无虚函数覆盖)

【VC++】虚函数 内存结构 - 第二篇(单继承,无虚函数覆盖) #include <IOSTREAM> using namespace std; class Base { public: int nBase1; int nBase2; Base(int n1,int n2):nBase1(n1),nBase2(n2) { cout<<"Base::Base("<<n1<<","<<n2<<")"<<end

maoyeahcom的博客 253

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VC_VC++类继承内存布局

上看到了一篇写得非常好的文章,是有关c++类继承内存布局的。看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用。 ——谈VC++对象模型 (美)简.格雷 程化    译 译者前言 一个C++程序员,想要进一步提升技术水平的话,应该多了解一些语言的语意细节。对于使用VC++的程序员来说,还应该了解一些VC++对于C++的诠释。 Inside the C++ Object

优快云-MarkYang 2541

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【C++ 篇 7】类的大小由什么决定?内存对齐、虚函数和纯虚函数的区别

内存对齐就是为了让内存存取更加有效率而采取的一种优化手段,对齐的结构是使得内存中数据的首地址是CPU单次获取数据大小的整数倍。

2401_85061293的博客 1030

【VC++】虚函数 内存结构 - 第三篇(单继承,有虚函数覆盖)

【VC++】虚函数 内存结构 - 第三篇(单继承,有虚函数覆盖) #include <IOSTREAM> using namespace std; class Base { public: int nBase1; int nBase2; Base(int n1,int n2):nBase1(n1),nBase2(n2) { cout<<"Base::Base("<<n1<<","<<n2<<")"<<end

maoyeahcom的博客 222

Vc++内存布局

Vc++内存布局 测试平台 Windows server 2012 R2 and visual studio 2013 professional。 本篇文章意在介绍vc++中类的内存布局方式,只是研究其大概的排列方式,对于内存对齐方面则没有进行深入探讨。如有需要研究类的具体大小可以参考其他博客。 测试方式 在vs中,查看类的内存布局主要有两种方式。一种是实例化一个类,然后在de...

antangzhang9759的博客 197

【VC++】虚函数 内存结构 - 第五篇(多重继承,有虚函数覆盖)

【VC++】虚函数 内存结构 - 第五篇(多重继承,有虚函数覆盖)

maoyeahcom的博客 254

VC++中的类的内存分布(上)

0.序   目前正在学习C++中,对于C++的类及其类的实现原理也挺感兴趣。于是打算通过观察类在内存中的分布更好地理解类的实现。因为其实类的分布是由编译器决定的,而本次试验使用的编译器为VS2015 RC,其编译环境为VC++,这里感谢@shenzhigang提醒。所以此处的标题为《VC++中的类的内存分布》。因为博主可能比较懒,所以把这个知识点分作两次写。( ╯□╰ )。 1.对...

diushi0625的专栏 163

【C++对象模型】使用gcc、clang和VC++显示C++类的内存布局

引言 各种C++实现对C++类/对象的内存布局可能有所不同,包括数据成员的顺序、虚函数表(virtual table: vtbl)的结构、继承关系的处理等。了解C++类/对象的布局,对于理解C++各种机制,正确合理地进行设计和开发有很大的帮助。 主流编译器的支持 本文所述的3款主流编译器都提供打印/导出C++类/对象的内存布局的功能,现用表格列出其特性和用法,测试用的代码文件列于文...

dengdi8115的博客 933

VC++ 查看类和对象的内存布局

类的内存布局 1. 在工程属性,C/C++ ==> 命令行 ==> 其他选项(D) 中输入如下编译选项: @1: /d1reportSingleClassLayout<name> 查看指定类的内存布局; 如查看类A, /d1reportSingleClassLayoutA @2: /d1reportAllClassLayout 查看所有...

huangdaxian114的博客 684

再谈带有虚函数的类对象之内存结构

前篇:http://blog.youkuaiyun.com/pathuang68/archive/2009/04/21/4096521.aspx 下面的代码中,类Base中定义了两个虚函数vfBase_1()和vfBase_2(),另外还定义了一个整形成员变量m_base;#include using namespace std; class Base{public:   

玄机逸士的专栏 1729

阿蓉之从零开始的【VC++ 】—— 结构体和类

ε=(´ο`*)))唉,看不懂tmc13代码,随便在柜子里找了一本年代久远的书,快速过一下前两章,零散的记录一些。 第一章 1、API函数( Application Programming Interface),应用程序编程接口 2、SDK(Software Development Kit),软件开发包 3、句柄Handle,相当于资源的标识号。窗口句柄HWND,若要对某个窗口进行操作,需要得到这个窗口的句柄。 4、C++与C相比有很多优点,主要体现在封装性(Encapsulation),继.

yamgyutou的博客 483

VC++类继承内存布局

——谈VC++对象模型 (美)简.格雷 程化    译 译者前言 一个C++程序员,想要进一步提升技术水平的话,应该多了解一些语言的语意细节。对于使用VC++的程序员来说,还应该了解一些VC++对于C++的诠释。 Inside the C++ Object Model虽然是一本好书,然而,书的篇幅多一些,又和具体的VC++关系小一些。因此,从篇幅和内容来看,译者认为本文是深入理解C

u013071074的专栏 905
上一篇: Release版崩溃,用VS调试dump文件,定位代码出错行【VC++/Visual Studio】
下一篇: 【VC++】虚函数 内存结构 - 第二篇(单继承,无虚函数覆盖)
maoyeahcom
博客等级 码龄15年 14粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值