100165351.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 150 行 · 第 1/2 页
HTM
150 行
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
7.3.2 使用指针优化性能
</title></head>
<body>
<div class="area">
<div class="col1">
<div class="lineBlue">
</div>
<!-- title -->
<div class="arcTitle">
<h1>
<a href="../16">
C#高级编程(第3版)【全文连载】
</a>
</h1>
<div style="text-align: center; font-size: 15px">
<a href="100165351.htm">
7.3.2 使用指针优化性能
</a>
</div>
<div style="text-align: center; font-size: 15px">
<a class="url" href="../../default.htm">http://book.csdn.net/</a>
2006-10-13 14:41:00
</div>
<div style="margin: 0px auto; width: 700px; border: solid 1px #0b5f98;">
<div style="float: left; width: 16px; background-color: #0b5f98; color: White; padding: 1px;">
图书导读
</div>
<div style="float: right; width: 670px; text-align: left; line-height: 16pt; padding-left: 2px">
<!--导读-->
<h1 id="divCurrentNode" style="color: #b83507; width: 100%; text-align: left; font-size: 12px; padding-left: 2px">当前章节:<a href='100165351.htm'><font color='red'>7.3.2 使用指针优化性能</font></a></h1>
<div id="divRelateNode" style="padding-left: 2px">
<div style='float:left;width:49%'>·<a href='100165348.htm'>7.3.1 指针(1)</a></div><div style='float:right;width:49%'>·<a href='100165349.htm'>7.3.1 指针(2)</a></div><div style='float:left;width:49%'>·<a href='100165350.htm'>7.3.1 指针(3)</a></div><div style='float:right;width:49%'>·<a href='100165352.htm'>7.4 小结</a></div><div style='float:left;width:49%'>·<a href='100165353.htm'>8.1 System.String类</a></div><div style='float:right;width:49%'>·<a href='100165354.htm'>8.1.1 创建字符串</a></div></div>
</div>
</div>
</div>
<!-- main -->
<div id="main">
<div id="text"> <link href="css.css" rel="stylesheet" type="text/css" /><h3 style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 0cm; MARGIN-RIGHT: 0cm; FTEL: 8.15pt"><a ftel="_Toc507815057"><span lang="EN-US">7.3.2 </span></a><span style="FONT-FAMILY: 黑体">使用指针优化性能</span></h3>
<p class="aa" style="LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体">前面用许多篇幅介绍了使用指针可以完成的各种任务,但在前面的示例中,仅是处理内存,让有兴趣的人们了解底层发生了什么事,并没有帮助人们编写出好的代码!本节将应用我们对指针的理解,用一个示例来说明使用指针可以大大提高性能。</span></p>
<h4 style="FTEL: 21.45pt"><span lang="EN-US">1. </span><span style="FONT-FAMILY: 黑体">创建基于堆栈的数组</span></h4>
<p class="MsoNormal" style="LINE-HEIGHT: 18pt"><a ftel="stackbased"><span style="FONT-FAMILY: 宋体">本节将介绍指针的一个主要应用领域:在堆栈中创建高性能、低系统开销的数组。第</span><span lang="EN-US">2</span></a><span style="FONT-FAMILY: 宋体">章介绍了</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">如何支持数组的处理。</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">很容易使用一维数组和矩形或锯齿形多维数组,但有一个缺点:这些数组实际上都是对象,是</span><span lang="EN-US">System.Array</span><span style="FONT-FAMILY: 宋体">的实例。因此数组只能存储在堆上,会增加系统开销。有时,我们希望创建一个使用时间比较短的高性能数组,不希望有引用对象的系统开销。而使用指针就可以做到,但只能用于一维数组。</span></p>
<p class="MsoNormal" style="LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体">为了创建一个高性能的数组,需要使用另一个关键字:</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">。</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">命令指示</span><span lang="EN-US">.NET</span><span style="FONT-FAMILY: 宋体">运行库分配堆栈上一定量的内存。在调用它时,需要为它提供两条信息:</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">要存储的数据类型</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span style="FONT-FAMILY: 宋体">需要存储的数据个数。</span></p>
<p class="MsoNormal" style="FTEL: 0cm"><span style="FONT-FAMILY: 宋体">例如,分配足够的内存,以存储</span><span lang="EN-US">10</span><span style="FONT-FAMILY: 宋体">个</span><span lang="EN-US">decimal</span><span style="FONT-FAMILY: 宋体">数据,可以编写下面的代码:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">decimal* pDecimals = stackalloc decimal [10];</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">注意,这个命令只是分配堆栈内存而已。它不会试图把内存初始化为任何默认值,这正好符合我们的目的。因为这是一个高性能的数组,给它不必要地初始化值会降低性能。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">同样,要存储</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">个</span><span lang="EN-US">double</span><span style="FONT-FAMILY: 宋体">数据,可以编写下面的代码:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">double* pDoubles = stackalloc double [20];</span></p>
<p class="MsoNormal" style="FTEL: 0cm"><span style="FONT-FAMILY: 宋体">虽然这行代码指定把变量的个数存储为一个常数,但它是在运行时计算的一个数字。所以可以把上面的示例写为:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">int size;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">size = 20; // or some other value calculated at run-time</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="FR">double* pDoubles = stackalloc double [size];</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">从这些代码段中可以看出,</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">的语法有点不寻常。它的后面紧跟的是要存储的数据类型名</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">该数据类型必须是一个值类型</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">,其后是把需要的变量个数放在方括号中。分配的字节数是变量个数乘以</span><span lang="EN-US">sizeof(</span><span style="FONT-FAMILY: 宋体">数据类型</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。在这里,使用方括号表示这是一个数组。如果给</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">个</span><span lang="EN-US">double</span><span style="FONT-FAMILY: 宋体">数据分配存储单元,就得到了一个有</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">个元素的</span><span lang="EN-US">double</span><span style="FONT-FAMILY: 宋体">数组,最简单的数组类型可以是:逐个存储元素的内存块,如图</span><span lang="EN-US">7-6</span><span style="FONT-FAMILY: 宋体">所示。</span></p>
<p align="center"><span lang="EN-US"><img height="167" src="07/image006.gif" width="203" alt="" /></span></p>
<p style="FTEL: 8.15pt" align="center"><span style="FONT-FAMILY: 宋体">图</span><span lang="EN-US"> 7-6</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在图</span><span lang="EN-US">7-6</span><span style="FONT-FAMILY: 宋体">中,显示了一个由</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">返回的指针,</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">总是返回分配数据类型的指针,它指向新分配内存块的顶部。要使用这个内存块,可以取消对返回指针的引用。例如,给</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">个</span><span lang="EN-US">double</span><span style="FONT-FAMILY: 宋体">数据分配内存后,把第一个元素</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">数组中的元素</span><span lang="EN-US">0)</span><span style="FONT-FAMILY: 宋体">设置为</span><span lang="EN-US">3.0</span><span style="FONT-FAMILY: 宋体">,可以编写下面的代码:</span></p>
<p class="a6" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="FR">double* pDoubles = stackalloc double [20];</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="FR">*pDoubles = 3.0;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">要访问数组的下一个元素,可以使用指针算法。如前所述,如果给一个指针加</span><span lang="EN-US">1</span><span style="FONT-FAMILY: 宋体">,它的值就会增加其数据类型的字节数。在本例中,就会把指针指向下一个空闲存储单元。因此可以把数组的第二个元素</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">数组中元素号为</span><span lang="EN-US">1)</span><span style="FONT-FAMILY: 宋体">设置为</span><span lang="EN-US">8.4</span><span style="FONT-FAMILY: 宋体">:</span></p>
<p class="a6" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="FR">double* pDoubles = stackalloc double [20];</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="FR">*pDoubles = 3.0; </span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">*(pDoubles+1) = 8.4;</span></p>
<p class="MsoNormal" style="FTEL: 0cm"><span style="FONT-FAMILY: 宋体">同样,可以用表达式</span><span lang="EN-US">*(pDoubles+X)</span><span style="FONT-FAMILY: 宋体">获得数组中下标为</span><span lang="EN-US">X</span><span style="FONT-FAMILY: 宋体">的元素。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这样,就得到一种访问数组中元素的方式,但对于一般目的,使用这种语法过于复杂。</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">为此定义了另一种语法。对指针应用方括号时,</span><span lang="EN-US">C#</span><span style="FONT-FAMILY: 宋体">为方括号提供了一种非常明确的含义。如果变量</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体">是任意指针类型,</span><span lang="EN-US">X</span><span style="FONT-FAMILY: 宋体">是一个整数,表达式</span><span lang="EN-US">p[X]</span><span style="FONT-FAMILY: 宋体">就被编译器解释为</span><span lang="EN-US">*(p+X)</span><span style="FONT-FAMILY: 宋体">,这适用于所有的指针,不仅仅是用</span><span lang="EN-US">stackalloc</span><span style="FONT-FAMILY: 宋体">初始化的指针。利用这个简捷的记号,就可以用一种非常方便的方式访问数组。实际上,访问基于堆栈的一维数组所使用的语法与访问基于堆的、由</span><span lang="EN-US">System.Array</span><span style="FONT-FAMILY: 宋体">类表示的数组是一样的:</span></p>
<p class="a6" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">double *pDoubles = stackalloc double [20];</span></p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?