看了很多值类型 和 引用类型的文章(谷歌能搜索出来的)
看了越多疑问越大,而这些资料中没有具体的说明。
问题:
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

值类型 引用类型 堆栈 堆 之 异想相关推荐

  1. 变量/值类型/引用类型/常量/枚举

    变量 声明语法 datatype identifier; 如:int i; //声明一个int类型的变量,但是在没有初始化之前编译器不允许使用该变量 同时声明多个 int a,b;//同时声明两个in ...

  2. javascript基本数据类型与值类型引用类型说明

    DEMO: http://sources.ikeepstudying.com/jsdata/ 摘要:本文主要讲了javascript中的基本数据类型,以及值类型和引用类型的区别与使用 一.基本数据类型 ...

  3. C#值类型-引用类型

    转换-值类型-引用类型-预定义分类表 转换 C#里,兼容的实例间可以进行相互转换 转换总是从一个值转换成一个新的值 隐式转换:隐式转换是自动发生的 显式转换:显式转换是手动操作的 长整型转换成整型的时 ...

  4. 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱

    引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并 ...

  5. iOS开发-Swift进阶之值类型 引用类型!

    本文主要介绍为什么结构体是值类型,类是引用类型 值类型 图片看不了请前往简书 前提:需要了解内存五大区,,如下所示 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XFI ...

  6. 关于C#值类型,引用类型,值传递,引用传递

    说到参数传递,必须得弄清值类型和引用类型: (为了容易表达,我暂且命名存放在堆中的内容为堆中对象,存放在栈上的内容为栈中对象.) 值类型存放在栈中,直接访问.如果有:int a=0;int b=a;就 ...

  7. C#基础_值类型引用类型(十一)

    值类型和引用类型: 值类型包括:byte,short,int,long,char,float,double,bool,struct结构 引用类型包括:类类型,接口类型和数组 等. 值类型和引用类型特点 ...

  8. C# 值类型 引用类型 作为参数传递区别

    C#数据类型分类: http://msdn.microsoft.com/zh-cn/library/t63sy5hs(v=VS.80).aspx. 值类型作为参数传递: http://msdn.mic ...

  9. 栈,堆,值类型,引用类型,装箱,拆箱 .NET中 6个重要的概念

    == 转载于:https://www.cnblogs.com/xiao-hei/p/3847525.html

最新文章

  1. mod_pagespeed
  2. java字节的输入输出流,java 字节输入输出流
  3. linux 进程调度类型 总结,Linux进程模型总结
  4. python创建数字列表_Python创建数字列表
  5. Git的smart Checkout\force checkout\Don‘t Checkout的区别
  6. 安卓平板运行python_使用Python进行手机平板移动开发 | 学步园
  7. jquery 实现智能炫酷的翻页相册效果
  8. 面试题,你觉得什么样的产品适合做成saas?
  9. assertionerror是什么异常_php7异常与错误处理和自定义异常
  10. windows 2008 R2操作系统上使用iis服务运行php和mysql数据库的网站遇到的验证码不显示问题?...
  11. 如何提高数据分析的效率
  12. Android Framework 全面分析 SystemServer
  13. PTA-1015——Reversible Primes
  14. 小游戏市场被微信点燃,社交平台蜂拥而至谁能分到蛋糕?
  15. landesk 卸载_landesk怎么卸载,软件卸载不了怎么办
  16. Axure原型图小字体在浏览器显示变大
  17. 计算机开机时间设置方法,win10系统设置电脑开关机时间的技巧介绍
  18. 电视家海信html安装不了,海信电视怎么看电视直播,安装电视家3.0解决方法
  19. 用c语言写出一个金字塔
  20. C++ QT调用python脚本并将软件打包发布

热门文章

  1. java file ip_java常用工具类 IP、File文件工具类
  2. 双网卡上网冲突解决_双网卡冲突解决方法——route命令
  3. python理论知识选择题_python基础知识练习题(一)
  4. 『数据库』数据库编程(概念性的东西,应用一般,甚至有点过时,用来考试)
  5. 如何理解和分析linux系统的CPU平均负载情况(load average)
  6. Python Data Science的多版本多环境管理工具Anaconda
  7. 使用线性回归的预测建模
  8. 空间谱专题02:波束形成(Beamforming)
  9. 萨义德与巴伦博依姆关于音乐和文学的对话
  10. stright 在mysql_MySQL优化的奇技淫巧之STRAIGHT_JOIN