值類型 引用類型 堆棧 堆 之 異想

看了很多值類型 和 引用類型的文章(谷歌能搜索出來的)
看了越多疑問越大,而這些資料中沒有具體的說明。
問題:
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.pswp.cn/news/260689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260689.shtml
英文地址,請注明出處:http://en.pswp.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…