tbwshc

tbw

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  95 Posts :: 8 Stories :: 3 Comments :: 0 Trackbacks

常用链接

留言簿(4)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

最近才知道struct和class的静态构造函数的触发规则是不同的,不像class在第一次使用类的时候触 发静态构造函数。如果只访问struct实例的字段是不会触发静态构造函数调用的。通过测试发现当访问静 态字段,struct本身的函数(静态和实例)和带参数的构造函数就会引起静态构造函数的执行。而调用默 认构造和未覆写的基类虚函数是不会的。为什么呢?

让我们先来看看class和struct在调用构造函数时的区别。class使用newobj指令而struct使用initobj 指令来构造对象。newobj在堆上申请一块内存并调用相应的构造函数进行初始化,然后将对象地址返回给 计算栈。initbobj则是从本地变量表中载入已经分配出来的struct实例然后初始化struct的各字段。这个 初始化过程是CLR内部执行的,而不像class编译器会给class添加一个默认构造函数(这就是为什么 struct不能给字段添加默认值的原因。但在类中如果给字段添加了默认值编译器就会自动在构造函数中添 加字段赋值操作)。如果给struct中定义了一个有参数的构造函数,那么系统就不会使用initobj指令, 而是直接用call指令调用带参数的构造函数。

我们最常见最常用的调用函数的指令是call和callvirt。对于静态函数使用call指令,对于class使用 callvirt指令(不论class中的函数是不是虚的)。只有子类调用父类的函数的时候(避免递归调用)以 及构造函数中(由编译器添加保证父类字段被初始化)使用call指令。而对于struct我们发现只要调用的 函数是struct本身定义的都是使用call指令。call和callvirt指令的差别在于,call会把调用的函数当作 静态函数看待,而不会关心调用当前函数时实例指针(this)是否为空。这就是struct调用函数时为什么 都是call因为struct实例是不可能被置为null的。实际上class在调用非虚函数时实际上也是使用call的 只是多做了一步验证——this是否为空,让我们来验证一下。

class Class_Test{  public void Test1() {}  public virtual void Test2()

{}  public static void Test3() {}  public override string ToString()  

{    return base.ToString();  }}Class_Test c = new Class_Test

();c.Test1();c.Test2();Class_Test.Test3();string str = c.ToString();

posted on 2012-07-21 11:54 tbwshc 阅读(1312) 评论(1)  编辑 收藏 引用

Feedback

# re: 由struct的静态构造函数说起 2012-07-21 22:27 likun
不是很理解,但是很有一套。
你的这个实例的作用是什么?看不到啊!!
大侠,给个输出,加上说明吧。。。。。。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理