值类型 引用类型 堆栈 堆 之 异想

看了很多值类型 和 引用类型的文章(谷歌能搜索出来的)
看了越多疑问越大,而这些资料中没有具体的说明。
问题:
1、堆栈 和 堆 分别存于计算机的哪个硬件(CPU缓存,内存,硬盘)?
2、为什么只有值类型和引用类型?
3、为什么说引用类型是指针?
4、堆栈必堆小小多少?
以下是个人的分析,不是权威结果。
1、堆栈 和 堆 分别存于计算机的哪个硬件(CPU缓存,内存,硬盘)?
使用排除法来看这个问题
(1)CPU缓存
(2)内存
(3)硬盘
(3)可以排除堆栈的可能,因为 硬盘最慢
(2)最有可能存堆栈,因为 速度适中,且相对来说存储空间足够大
(1)可能性很小,应为仅几年来CPU的缓存越来越大 但目前家用级别的CPU的1,2,3级缓存很少超过10MB(多核情况下每个核心分到的更少);
真像可能就是堆栈和堆都是放在内存里的。
那么为什么堆栈比堆快呢?
个人认为这情况和hashtable与list等数据容器的差异,差不多。
存取方式决定的。
堆栈:只能存取值类型,且先进先出,不够的时候直接压栈(就像"向右看起"的命令一样) --简单快捷
堆:首先,堆的分配模式会存在碎片,并不是连续性的(这里直的是多个对象,找到一个适合的内存空间就把对象放进去,就像家居摆放物件一样,有时候不贴个纸条的话,得找半天)。
2、为什么只有值类型和引用类型?
这个我觉得追溯到本源比较好解释,就是CPU只能进行数学计算。(看下汇编代码会好理解些)
值类型:就是数字,CPU可以直接进行运算。
引用类型:最终指向值类型的指针。object是指针,object的ToString的函数还是一个指针,ToString内有String类型还是指针,最终指向一个Char[] 字符集合
(注,我对String的理解就是Char[])。
所以对象无法直接进行运算,只能通过指针找到能运算的部分,再进行运算。这也就是为啥只有2个类型了,一个是值用于运算,一个是指针,指向需要运算的地方。
3、为什么说引用类型是指针?
由上可知,引用类型是指针必然性。
一个Class内除了Int32等 值类型外其他皆是指针,委托,函数,函数内的对象,属性,事件 都是指针。
根据这种特性,指针(引用类型)作为参数传递,出来的时候会根据函数内的改变而改变,而值要作为参数输入并输出的话就要ref了。
(注: 个人发现 DateTime 作为参数时具有值类型的特征)
4、堆栈必堆小小多少?
未知,希望有知道的朋友能给出测试方法或者结果
我的推测是既然是在内存,必然没有限制,除非人为的限制
我使用线程测试内存上限时发现没有具体的上限。我的是64位+8G内存的笔记本以下是测试结果:(线程内分别创建class和sturct)
X86: 一个应用程序只能达到1300多一点的线程,再也上不去了,提交内存约1440k
class:运行稳定。sturct:大约2分钟 内存溢出
X64:一个应用程序只能达到8000多的线程,提交内存约10000k(还能继续)
class:运行稳定。sturct:行稳定
最终 我的结论:在C#里class 和sturct 如果真的是一个分配在堆,一个分配在堆栈,那么堆栈和堆的空间大小没有区别,只存在速度的区别
以下是测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (var i = 0; i < 10000; i++)
{
Thread th = new Thread(() =>
{
abc a = new abc(1);
});
th.Start();
}
Console.ReadKey();
}
}
struct abc
{
public abc(Int32 x)
{
ds = String.Empty;
Test();
}
String ds;
private void Test()
{
while (true)
{
ds += "A";
Thread.Sleep(1000);
}
}
}
class bc
{
public bc(Int32 x)
{
ds = String.Empty;
Test();
}
String ds;
private void Test()
{
while (true)
{
ds += "A";
Thread.Sleep(1000);
}
}
}
}
IL:

class 的

// 代码大小 28 (0x1c)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldsfld string [mscorlib]System.String::Empty
IL_000e: stfld string ConsoleApplication1.bc::ds
IL_0013: ldarg.0
IL_0014: call instance void ConsoleApplication1.bc::Test()
IL_0019: nop
IL_001a: nop
IL_001b: ret
} // end of method bc::.ctor
sturct 的
// 代码大小 20 (0x14)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldsfld string [mscorlib]System.String::Empty
IL_0007: stfld string ConsoleApplication1.abc::ds
IL_000c: ldarg.0
IL_000d: call instance void ConsoleApplication1.abc::Test()
IL_0012: nop
IL_0013: ret
} // end of method abc::.ctor
堆栈容量测试:
using System;
using System.Threading;
namespace ConsoleApplication1
{class Program{static void Main(string[] args){String txt = System.IO.File.ReadAllText("demo.txt");//一个3.11MB的文本
Thread th = new Thread(() =>{abc a = new abc(1);for (var i = 0; i < 1000; i++){a.ds += txt;}});th.Start();Console.ReadKey();}}struct abc{public abc(Int32 x){ds = String.Empty;}public String ds;}}

测试结果:X64 能 提交内存3000K以上

 


我的结论和想法是这样的:

首先我是站在CPU的角度去思考的。

1、堆栈 堆 可能都是一样的指针,他们本身只是数据容器。

2、他们的区别在于存取方式不一致导致的存取速度不一样。

3、堆栈 和堆 没有具体大小,除非人为设置,且很有可能由CLR或者编译器动态选择数据容器。(毕竟我只能看到IL,看不到先X86反编译汇编)

4、值类型传参实为传值,引用类型传参实为传地址(指针),这也是堆栈和堆数据使用上的区别。CPU对堆栈的态度是拿来就用,对堆就是找到再用。

通过 Wiz 发布



转载于:https://www.cnblogs.com/tianjing/archive/2012/07/03/2574577.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

漫步者lollipods如何调节音量_漫步者MF5扩音器体验:老师值得入手

对于教师职业来说&#xff0c;保护好嗓子是很重要的。每天为学生操劳&#xff0c;频繁的讲课&#xff0c;很多老师都遇上了喉咙沙哑的问题。怎么样才能保护好老师的嗓子呢&#xff1f;“小蜜蜂”是很多老师们的选择&#xff0c;这种扩音器可以挂在腰间&#xff0c;通过麦克风&a…

数据库之间数据转换最快方法

用txt导入的方式是最快的&#xff0c;一般是秒级。 以ACCESS数据库到SQLite数据库为例&#xff1a; 第一步&#xff1a;导出ACCESS数据库到txt文件&#xff1a; 一、将表中数据导出到文本文件&#xff08;TXT&#xff09;&#xff1a; Select * INTO [TEXT;DATABASEE:\TEMP].TE…

pandas删除某列有空值的行_Python-零基础学习Pandas知识点整理(2)

DataFrame数据的清洗--预处理操作import pandas as pdimport numpy as np#DataFrame数据框行或列的删除#df.drop(labelsNone,axis0,indexNone,columnsNone,levelNone,inplaceFalse,error"raise")#labels 表示需要删除的行或列的标签&#xff0c;多行或多列用列表传入…

JavaScript中的闭包

什么是闭包&#xff1f; 当函数可以记住并访问所在的词法作用域时&#xff0c;就产生了闭包&#xff0c;即使函数是在当前词法作用域之外执行的。下面用一些代码来解释这个定义&#xff1a; function foo() {var a 2;function bar() {console.log(a); // 2}bar(); }foo(); 这…

第4章 Python 数字图像处理(DIP) - 频率域滤波12 - 选择性滤波 - 带阻

目录选择性滤波带阻滤波器和带通滤波器陷波滤波器选择性滤波 处理特定的频带的滤波器称为频带滤波器 带阻滤波器&#xff1a; 若某个频带中的频率被滤除 带通滤波器&#xff1a; 若某个频带中的频率被通过 处理小频率矩形区域的滤波器称为陷波滤波器 陷波带阻滤波器&#x…

command line

对chrome 的IPC 感兴趣&#xff0c;想通过他的单元测试来窥探。 无意中看到有一个command_line 类&#xff0c;因为是第二次碰到 &#xff2f;&#xff33;&#xff27;中也有一个&#xff43;&#xff4f;&#xff4d;&#xff4d;&#xff41;&#xff4e;&#xff44;类正好…

[物理学与PDEs]第1章第4节 电磁能量和电磁动量, 能量、动量守恒与转化定律 4.3 电磁能量 (动量) 密度, 电磁能量流 (动量流) 密度...

1. 电磁能量密度: $\cfrac{1}{2}\sex{\ve_0E^2\cfrac{1}{\mu_0}B^2}$. 2. 电磁能量流密度向量: ${\bf S}\cfrac{1}{\mu_0}{\bf E}\times {\bf B}$. 3. 电磁动量密度向量: $\cfrac{1}{c^2}{\bf S}$. 4. 电磁动量流密度张量: $\cfrac{1}{2}\sex{\ve_0E^2\cfrac{1}{\mu_0}B^2}{\bf…

python打包工具报错_python打包生成exe报错

如图所示 如果出现的是这个问题可以可以考虑以下方法 首先卸载原先下载的 Pyinstaller pip uninstall pyinstaller 再执行以下代码&#xff0c;去github上下载 pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip 注释&#xff1a;再次打包&#xff…

创建DLL、Lib以及使用DLL、Lib

1.要在生成DLL文件的同时生成Lib文件&#xff0c;函数声明时前面要加__declspec(dllexport)。 可在头文件中如下定义&#xff1a; #ifndef __MYDLL_H #define __MYDLL_H#ifdef MYDLL_EXPORTS #define MYDLL __declspec(dllexport) #else #define MYDLL __declspec(dllimport) #…

去除lcd图片的摩尔纹_宝妈时尚产后有妊娠纹怎么办?教你这三招,轻松修复肚皮!...

产后肚子上长妊娠纹&#xff0c;相信是很多妈妈的痛点。首先我们来介绍一下什么是妊娠纹。由于妊娠期荷尔蒙的影响&#xff0c;加之腹部膨隆使皮肤的弹力纤维与胶原纤维损伤或断裂&#xff0c;腹部皮肤变薄变细&#xff0c;出现一些宽窄不同、长短不一的粉红色或紫红色的波浪状…

anaconda 换清华镜像源 windows

方法1 Windows 下安装好Anaconda 应该会有如下这些应用&#xff0c;我们打开如下图anaconda Prompt(下面简称prompt)&#xff0c;(当然CMD也可以&#xff0c;只是我比较喜欢用prompt) 打开如下图 使用下面命令&#xff0c;即可以添加清华镜像 conda config --add channels …

php冒泡排序和快速排序笔记

<?php $arr array(12,1,5,88,35,0,18,100,50,21,28,7,9,9.5);//交换两值 function swap(&$m, &$n){$temp $m;$m $n;$n $temp;/* 如数组中有小数时&#xff0c;以下方法会省略小数点后面的数$m $m ^ $n;$n $m ^ $n;$m $m ^ $n;*/ }//冒泡排序 function bubbl…

提高表格可读性的一些技巧

表格的应用由于工作原因&#xff0c;经常接触到表格。我们发现&#xff0c;表格不但广泛的运用在各类数据收集和分析&#xff0c;同时通过表格这样一种二维矩阵来整理和陈列信息时&#xff08;即便最后的展示方式并非一个典型的表格样式&#xff09;&#xff0c;能够很好的表达…

分页第一页用0还是1_如何设计api分页

常规的分页方式API处理分页看似简单&#xff0c;实际上暗藏危机。最常见的分页方式&#xff0c;大概是下面这样的/users/?page1&limit5//服务端返回最理想的情况下&#xff0c;客户端请求第一页的5条数据&#xff0c;服务端如常返回&#xff0c;比如下图:拿Twitter的图用一…

数据挖掘肿瘤预测_科研套路不嫌多,数据挖掘发3分

解螺旋公众号陪伴你科研的第2003天如何复现一篇3分生信研究做科研需要先学习套路&#xff0c;才能超越套路。今天给大家介绍的套路文献是今年发表在《Oncology reports》(IF 3.041)上的一篇文章。文章的标题虽然看上去比较泛&#xff0c;但也让读者一眼就能知道主题了&#xff…

Jupyter notebook 导出PDF的3种方法

很多用Jupyter notebook的都想导出PDF&#xff0c;但是我们点击Download as PDF via LaTex. 然后呢&#xff1f; Ohzzzzzzzzz 出现下图的错误&#xff0c;看到这里感觉糟糕透啦。虽然可以根据提供的方法解决这个问题。下面我说说我的方法吧。 方法1 打开jupyter notebook&a…

mybatis中的#{value}和${value}的区别

2019独角兽企业重金招聘Python工程师标准>>> 1. #{value}将传入的数据都当成一个字符串&#xff0c;会对自动传入的数据加一个双引号。 2. ${value}将传入的数据直接显示生成在sql中。 3. #{value}方式能够很大程度防止sql注入。  4.${value}方式无法防止Sql注入。…

数据库备份失败问题

备份对于服务器“服务器名”失败。&#xff08;Microsoft.SqlServer.Smo&#xff09; 其他信息&#xff1a;System.Data.SqlClient.SqlError:无法打开备份设备c:\abc.bak。出现操作系统错误5(拒绝访问。)。(Microsoft.SqlServer.Smo&#xff09; 解决办法&#xff1a; Sql Serv…

重写setTimeout扩展参数

1 //判断函数行参长度来决定是否需要重写setTimeout&#xff0c;ie8以下为undefined2 if(window.setTimeout.length undefined){3 var __sto window.setTimeout;4 window.setTimeout function(callback,timeout,param){5 var args Array.prototype.slice.c…

针对access数据库的增删改查

1、执行查询操作&#xff1a;&#xff08;ExecuteReader方法&#xff09; string myConnectionString "Provider Microsoft.Jet.OLEDB.4.0;Data Source "Server.MapPath("~/") "App_Data/access.mdb"; //使用相对路径连接数据库 string mySel…