求一个C#中使用高性能数组(使用指针)的实际应用

大家都知道,在C#不安全的代码中可以使用Stackalloc创建一个基于堆栈的数组,我现在想知道的是,在实际的项目开发中,什么时候会用到它?

如果您具体的有针对性的回答了这个问题(一定要有具体的应用环境),本问题的50分就给您。
如果您能详细的描述一下,如给出具体的算法,也就是说我能根据您的说明编写出一个实际应用的程序示例,那么我给您追加100分。

PS:请直接在下面回答,貌似一加上邮箱或QQ问题就被删除了,郁闷!
小花朵8,你好,翻转图片也有函数实现,所以这个不算是具体应用了,谢谢!

stackalloc 创建一个高性能的数组

stackalloc命令指示.NET运行库分配堆栈上一定量的内存。在调用它时,需要为它提供两条信息:
● 要存储的数据类型
● 需要存储的数据个数。
例如,分配足够的内存,以存储10个decimal数据,可以编写下面的代码:
decimal* pDecimals = stackalloc decimal [10];
注意,这个命令只是分配堆栈内存而已。它不会试图把内存初始化为任何默认值,这正好符合我们的目的。因为这是一个高性能的数组,给它不必要地初始化值会降低性能。
同样,要存储20个double数据,可以编写下面的代码:
double* pDoubles = stackalloc double [20];
虽然这行代码指定把变量的个数存储为一个常数,但它是在运行时计算的一个数字。所以可以把上面的示例写为:
int size;
size = 20; // or some other value calculated at run-time
double* pDoubles = stackalloc double [size];
从这些代码段中可以看出,stackalloc的语法有点不寻常。它的后面紧跟的是要存储的数据类型名(该数据类型必须是一个值类型),其后是把需要的变量个数放在方括号中。分配的字节数是变量个数乘以sizeof(数据类型)。在这里,使用方括号表示这是一个数组。如果给20个double数据分配存储单元,就得到了一个有20个元素的double数组,最简单的数组类型可以是:逐个存储元素的内存块,如图7-6所示。

图 7-6
在图7-6中,显示了一个由stackalloc返回的指针,stackalloc总是返回分配数据类型的指针,它指向新分配内存块的顶部。要使用这个内存块,可以取消对返回指针的引用。例如,给20个double数据分配内存后,把第一个元素(数组中的元素0)设置为3.0,可以编写下面的代码:
double* pDoubles = stackalloc double [20];
*pDoubles = 3.0;
要访问数组的下一个元素,可以使用指针算法。如前所述,如果给一个指针加1,它的值就会增加其数据类型的字节数。在本例中,就会把指针指向下一个空闲存储单元。因此可以把数组的第二个元素(数组中元素号为1)设置为8.4:
double* pDoubles = stackalloc double [20];
*pDoubles = 3.0;
*(pDoubles+1) = 8.4;
同样,可以用表达式*(pDoubles+X)获得数组中下标为X的元素。
这样,就得到一种访问数组中元素的方式,但对于一般目的,使用这种语法过于复杂。C#为此定义了另一种语法。对指针应用方括号时,C#为方括号提供了一种非常明确的含义。如果变量p是任意指针类型,X是一个整数,表达式p[X]就被编译器解释为*(p+X),这适用于所有的指针,不仅仅是用stackalloc初始化的指针。利用这个简捷的记号,就可以用一种非常方便的方式访问数组。实际上,访问基于堆栈的一维数组所使用的语法与访问基于堆的、由System.Array类表示的数组是一样的:
double *pDoubles = stackalloc double [20];
pDoubles[0] = 3.0; // pDoubles[0] is the same as *pDoubles
pDoubles[1] = 8.4; // pDoubles[1] is the same as *(pDoubles+1)

注意:
把数组的语法应用于指针并不是新东西。自从开发出C和C++语言以来,它们就是这两种语言的基础部分。实际上,C++开发人员会把这里用stackalloc获得的、基于堆栈的数组完全等同于传统的基于堆栈的C和C++数组。这个语法和指针与数组的链接方式是C语言在70年代后期流行起来的原因之一,也是指针的使用成为C和C++中一种大众化编程技巧的主要原因。
高性能的数组可以用与一般C#数组相同的方式访问,但需要强调其中的一个警告。在C#中,下面的代码会抛出一个异常:
double [] myDoubleArray = new double [20];
myDoubleArray[50] = 3.0;
抛出异常的原因很明显。使用越界的下标来访问数组:下标是50,但允许的最大值是19。但是,如果使用stackalloc声明了一个相同数组,对数组进行边界检查时,这个数组中没有包装任何对象,因此下面的代码不会抛出异常:
double* pDoubles = stackalloc double [20];
pDoubles[50] = 3.0;
在这段代码中,我们分配了足够的内存来存储20个double类型数据。接着把sizeof(double)存储单元的起始位置设置为该存储单元的起始位置加上50*sizeof(double)存储单元,来保存双精度值3.0。但这个存储单元超出了刚才为double分配的内存区域。谁也不知道这个地址上存储了什么数据。最好是只使用某个当前未使用的内存,但所重写的空间也有可能是堆栈上用于存储其他变量或某个正在执行的方法的返回地址。因此,使用指针获得高性能的同时,也会付出一些代价:需要确保自己知道在做什么,否则就会抛出非常古怪的运行时错误。
2. 示例QuickArray
下面用一个stackalloc示例QuickArray来结束关于指针的讨论。在这个示例中,程序仅要求用户提供为数组分配的元素数。然后代码使用stackalloc给long型数组分配一定的存储单元。这个数组的元素是从0开始的整数的平方,结果显示在控制台上:
using System;

namespace Wrox.ProCSharp.Chapter07
{
class MainEntryPoint
{
static unsafe void Main()
{
Console.Write("How big an array do you want? \n> ");
string userInput = Console.ReadLine();
uint size = uint.Parse(userInput);

long* pArray = stackalloc long [(int)size];
for (int i=0 ; i pArray = i*i;

for (int i=0 ; i Console.WriteLine("Element {0} = {1}", i, *(pArray+i));
}
}
}
运行这个示例,得到如下所示的结果:
QuickArray
How big an array do you want?
> 15
Element 0 = 0
Element 1 = 1
Element 2 = 4
Element 3 = 9
Element 4 = 16
Element 5 = 25
Element 6 = 36
Element 7 = 49
Element 8 = 64
Element 9 = 81
Element 10 = 100
Element 11 = 121
Element 12 = 144
Element 13 = 169
Element 14 = 196
7.4 小结
要想成为真正优秀的C#程序员,必须牢固掌握存储单元和垃圾收集的工作原理。本文描述了CLR管理以及在堆和堆栈上分配内存的方式,讨论了如何编写正确释放未托管资源的类,并介绍如何在C#中使用指针,这些都是很难理解的高级主题,初学者常常不能正确实现。

本文摘至清华大学出版社出版的Wrox红皮书《C#高级编程(第3版)》,
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-07-20
说实话这个东西我在工作中也没怎么用到过
不过既然涉及到指针方面的操作肯定是问题提高性能才使用的
以前只遇到过一个类似问题,就是需要把一个1280x1024的图片翻转,如果用简单的数组循环,你会发现完全不能接受。但是如果你用指针通过直接矩阵计算,直接寻找地址的话,很快!
所以,我感觉这个地方也是为了提供内存级别的访问,以提高某些代码的性能
有篇文档你看看,对你有帮助
http://wenku.baidu.com/view/c4dc40768e9951e79b8927aa.html
第2个回答  2010-07-20
呵呵,我用过,我用在人脸识别的计算上了,因为效率要求比较高需要在25ms秒内完成较为复杂的图像检测和图像识别,所以用了非安全代码,不过后来水平提高了,我就把非安全代码修改为安全代码了,而且效率比以前的还略高一些,这个反正就是通过工具可以提高效率,通过思想也可以提高效率,

呵呵,希望我的经历对你有用。本回答被提问者采纳
第3个回答  2010-07-20
在C#实际开发过程中极少用到指针,因为指针在c#中有很多限制(由于托管的架构),也不如C++方便。而且,C#中的指针性能并不高,我测试过,还不如一些包装好的类或API。我至今也没有找到什么可以实际应用。
相似回答