相信很多人在这样或那样的项目中,或者无意间看到了fixed语句块,看到之后你肯定会疑问:

1,这个fixed关键字是做什么用的?

2,什么情况下需要该关键字?

3,这个关键字该怎么用?

我相信解决了上面四个问题之后,你对这个fixed语句就理解和掌握到位了,我也在网上大致浏览了下,网上关于该关键字的详细说明太少太少了,基本都是摘抄MSDN官方文档,毫无自身理解与发散出来的东西,当然完全依据MSDN的只言片文也能理解不过相当费劲,在这里我结合自己的理解给大家说明下该关键字的用法,希望各位看过之后能给出自己的想法。

本文地址:http://hi.baidu.com/jiang_yy_jiang/blog/item/de22fcd15d017f269a502770.html

在MSDN如下介绍:

1、fixed 语句禁止垃圾回收器重定位可移动的变量。fixed 语句只能出现在不安全的上下文中。Fixed 还可用于创建固定大小的缓冲区。
2、fixed 语句设置指向托管变量的指针并在 statement 执行期间“钉住”该变量。如果没有 fixed 语句,则指向可移动托管变量的指针的作用很小,因为垃圾回收可能不可预知地重定位变量。C# 编译器只允许在 fixed 语句中分配指向托管变量的指针。
3、执行完语句中的代码后,任何固定变量都被解除固定并受垃圾回收的制约。因此,不要指向 fixed 语句之外的那些变量。

看到这几乎话你可能云里雾里,雾里云里,

第一句:fixed禁止垃圾回收器定位可移动变量这到底是怎么一回事?

如果你不理解这句话说明你得需要去了解下GC,我们知道GC是CLR管理下的垃圾回收器。当进程初始化时,CLR保留一块连续的地址空间,这个地址空间最初并没有对应的物理存储空间,这个地址空间就是托管堆。在托管堆中,连续分配的对象可以确保他们在内存中时连续的。托管堆维护着一个叫做NextObjPtr的指针,它指向下一个对象在堆中的分配位置。调用new操作符创建对象时,如果没有足够的地址空间来分配对象,也即对象的字节数+NextObjPtr指针的地址超过了地址空间末尾则需要进行一次垃圾回收。

回收机制是采用根标记堆上的对象,当根不可达时则回收堆所占的内存(这里不去扩展,只给个大概的脉络,其实还涉及GC的代Generation),当回收完毕时的下一阶段就是压缩内存,这个阶段垃圾回收器线性的便利堆,以寻找未标记(垃圾)对象的连续内存块,如果发现的内存块比较小,垃圾回收期会忽略它们,但是,如果发现大的,可用的连续内存块,垃圾回收器会把非垃圾的对象移动到这里以压缩堆。

很自然地,移动内存中的对象之后,包含“指向这些对象的指针”的变量和CPU寄存器现在都会变得无效。所以垃圾回收器必须重新访问应用程序的所有根,并修改它们来指向对象的新内存位置。另外,如果对象中的字段指向的是另一个已移动了位置的对象,垃圾回收器要负责更正这些字段。堆内存压缩之后,托管堆的NextObjPtr指针指向紧接在最后一个非垃圾对象之后的对象之后的位置。

   到这里......哇 看了这么久你肯定累了,可以休息下哈.................................................................................................

上面所说的都是在托管环境的CLR指导下完成的,那如果是非安全代码如果是指针呢?指针指向了一个托管对象,而GC时内存会压缩,谁还管你的非安全指针,我们CLR只负责托管代码啊!所以微软给出的解决办法是采用fixed关键字。

   所以当你看完到这里而且明白的话第1,2个问题都解决啦!!

   对于第三个问题,我采用一个实例结合MSDN说明:

结合上面的理论,如果还能输出结果说明指针操作成功,没有因为GC的回收造成指针操纵了不正确的地址,因为fixed语句块钉住了ints变量,禁止垃圾回收器操作内存地址,重定位可移动变量。为什么要这样做呢?我们不是可以用托管代码直接操作数组吗?

没错,但你别忘了指针操作数组是很快的,因为它会关闭数组索引的检查即关闭索引的上下限检查,这样的好处是:你的程序是性能优先,以性能为核心的时候这反而是最佳的解决方案!

C# fixed语句固定变量详解的更多相关文章

  1. [转]mysqldump备份还原和mysqldump导入导出语句大全详解

    FROM : http://www.cnblogs.com/zeroone/archive/2010/05/11/1732834.html mysqldump备份还原和mysqldump导入导出语句大 ...

  2. shell 脚本之判断语句 if 详解

    使用 Linux 系统这么长时间,对 shell 脚本也算是比较熟悉.其实不管是搞开发,还是搞运维,shell 脚本都是必备的基本技能.这次抽时间好好总结一下 shell 方面的知识,综合的再学习一下 ...

  3. MySQL查询语句(select)详解(2)

    7.子查询 当进行查询的时候,需要的条件是另外一个select语句的结果,这时候就要用到子查询 用于子查询的主要关键字有:in,not in,=,!=,exists,not exists等. 以下两张 ...

  4. static{ }语句块详解

    static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法.举ge例子: public class Test { public static i ...

  5. 转 java中static{}语句块详解

    原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430     感谢原作者! static{}(即static块),会在类被加载的时候执 ...

  6. java中static{}语句块详解

    static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次执行过程中,stati ...

  7. hive操作语句使用详解

    #创建表人信息表  person(String name,int age) hive> create table person(name STRING,age INT)ROW FORMAT DE ...

  8. SQL语句函数详解__sql聚合函数

    函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类:单行函数.组函数 本文将讨论如何使用单行函数及 ...

  9. JavaScript 循环语句入门详解

    JavaScript Switch 语句 语法 switch(n) { case 1: 执行代码块 1 break; case 2: 执行代码块 2 break; default: n 与 case ...

随机推荐

  1. tableau desktop(三)--构建数据视图(二)

    前段时间忙于工作的事情,好久没有来记录一点东西了,今天利用周末做点记录吧,近期因为工作的原因,也有两三周没实用tableau了.今天继续上一篇构建数据试图(二). 3.7 參考线和參考区间 參考线通经 ...

  2. 深刻理解Docker镜像大小

    都说容器大法好,可是假设没有Docker镜像,Docker该是多无趣啊. 是否还记得第一个接触Docker的时候,你从Docker Hub下拉的那个镜像呢?在那个处女镜像的基础上.你执行了容器生涯的处 ...

  3. CentOS6.3升级GCC到GCC4.8.2

    server上安装的GCC版本号过旧.已经不满足个人使用的版本号需求,故决定对其进行升级操作.由当前版本号3.4.6升级到4.8.2.然受权限制约.仅仅能安装到个人文件夹.因此假设您的server能够 ...

  4. JAVA设计模式之【外观模式】

    通过引入一个外观角色来简化客户端与子系统之间的交互. 顾客无需直接和茶叶.茶具.开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可. 通过引入一个外观角色可以降低原有系统的复杂度,同时降 ...

  5. php中echo什么时候用到\"这个符号

    php中echo什么时候用到\"这个符号 当在引号中用到引号时,为避免混乱用\" \称为转义符,表示后面的字符和原来程序语言里的语法符号含义不同 常见的转义有 \" \' ...

  6. javascript系列-class3.循环语句

    欢迎加入前端交流群来py: 转载请标明出处! while循环   while(循环终止条件){       }   案例     输出0~100个数字  1 . 3 .  5 不输出   输出一百数字 ...

  7. HD-ACM算法专攻系列(4)——A == B ?

    题目描述: 源码: /**/ #include"iostream" #include"string" using namespace std; string S ...

  8. CentOS 安装 MySQL8

    @Linux 官网:https://dev.mysql.com/doc/refman/8.0/en/binary-installation.html 个人博客:https://www.xingchen ...

  9. 【转载】tom的RUNSTATS测试工具

    -- 创建 runstats 包.其中包括 3 个简单 API 调用: create or replace package runstats_pkg as procedure rs_start; pr ...

  10. 对称平方数(to_string函数,stoi函数真香)

    题目描述 打印所有不超过n(n<256)的,其平方具有对称性质的数.如11*11=121. 输入描述: 无 输出描述: 每行一个数,表示对称平方数. 示例1 输入 复制 无 输出 复制 无解题思 ...