谈C#与C++在静态构造函数上的区别

  在C#中,类的静态构造函数用于在使用类之前进行相关的初始化工作;比如,初始化静态成员或执行特定操作。CLR 在第一次创建该类对象或调用该类静态方法时自动调用静态构造函数。同时,CLR保证静态构造函数的线程安全性(准确地说是,只会调用一次,不存在多线程问题)。

  下面是MSDN对静态构造函数特点的描述:

  1.静态构造函数既没有访问修饰符,也没有参数

  2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类

  3.无法直接调用静态构造函数

  4.在程序中,用户无法控制何时执行静态构造函数

  C++语言规范并未包含类似静态构造函数的东西,但在使用类之前做初始化工作的需求却是客观存在的。就满足需求本身来讲,C++完全可以通过手动方式实现,但要处理好初始化时机,线程安全性等问题。本文则尝试通过C++的模版机制模拟实现静态构造函数,避免手动初始化的繁琐实现。对于需要静态构造函数的类A,只需用继承static_constructable模版类,并提供 static void statici_constructor()静态方法即可:


  输出:


  下面是static_constructable类模板的实现:


  上面的实现把对A::static_constructor()的回调放到内部类helper的构造函数中;并在static_constructable()中定义一个helper局部静态变量;C++保证在构造派生类 A的对象时,会先调用基类static_constructable的构造函数,且静态局部变量只会构造一次,这样就达到调用一次且仅一次A::static_constructor()的目的。

  static_constructor类模板简单地模拟了C#的静态构造函数机制,它具有以下特点:

  1. 在第一次构造类对象之前自动调用类提供的静态构造函数

  2. 静态构造函数被调用的时机是确定的

  3. 利用了C++的局部静态变量初始化机制保证了线程安全性(更正:实际并非线程安全,C++标准不涉及多线程问题,而一般编译器实现也非线程安全,更多参见评论部分)

  4. 基于继承的实现机制并未改变派生类的对象内存布局

  不过,和本文开始列出的C#静态构造函数的几个特点相比,本实现还有明显的不足:无法通过调用类A的静态方法触发静态构造函数;类A的静态构造函数必须是public的。

时间: 2024-07-31 08:09:29

谈C#与C++在静态构造函数上的区别的相关文章

艾伟_转载:静态构造函数趣谈!

类的静态构造函数也叫类型构造器,静态构造器,他调用的时刻由CLR来控制: CLR会选择如下时间之一来调用静态构造函数:      1,在类型的第一个实例创建之前,或类型的非继承字段或成员第一次访问之前.这里的"之前",代表前后衔接的意思.这里的时刻是精确的!      2,在非继承的静态字段或成员第一次访问之前的某个时刻,具体时刻不定! 由于调用的时刻不确定,所以我们最好不要编写依赖于特定的静态构造函数的执行顺序的代码,这样很容易产生不可预料的后果! 下面大家看三个Demo,我们来更加

静态构造函数趣谈!

类的静态构造函数也叫类型构造器,静态构造器,他调用的时刻由CLR来控制: CLR会选择如下时间之一来调用静态构造函数:      1,在类型的第一个实例创建之前,或类型的非继承字段或成员第一次访问之前.这里的"之前",代表前后衔接的意思.这里的时刻是精确的!      2,在非继承的静态字段或成员第一次访问之前的某个时刻,具体时刻不定! 由于调用的时刻不确定,所以我们最好不要编写依赖于特定的静态构造函数的执行顺序的代码,这样很容易产生不可预料的后果! 下面大家看三个Demo,我们来更加

C#箴言:用静态构造函数初始化静态成员

函数|静态 编写程序的时候难免要使用到静态成员,由于静态成员的访问是脱离类型对象的,所以使用非静态构造函数,私有方法或者一些其他方法都是不合理的..Net提供了成员初始化语句和静态构造函数来初始化静态成员. 根据上一个单元,我们可以知道静态成员的初始化语句会早于静态构造函数执行,其次还知道成员初始化语句的好处和一些限制.这里要提的一点就是,静态构造函数和实例构造函数之间的区别,因为静态构造函数是由CLR调用执行的,所以静态构造函数只能是一个,同时不能还有参数.那么静态构造函数相对于成员初始化的一

由struct的静态构造函数说起

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

利用静态只读字段和静态构造函数提高性能

主要内容一句话概括: 把相对固定的数据在编译时仅通过查询一次数据库填充到公开的静态只读泛型集合类型字段中从而杜绝后续可能的数据库查询以提高性能. 相关背景:我们的应用程序中常常需要一些类似全国的省份列表这样的集合数据,而这些数据基本上是固定不变的或者是很长时间才会变一次.对于这样的数据,开发中我们常用的一个做法就是把这些数据存在数据库表中,然后查询填充到需要的地方.我觉得这种做法很脏,因为我们多次去查询这些固定不变的数据没有什么意义,或者进一步我们顶多缓存这些数据以避免一些查询以提高性能,也就是

Effective C#原则13:用静态构造函数初始化类的静态成员

(译注:initializer在上文中译为了"初始化器",实在不好听 ,本文中全部改译为:"预置方法") 你应该知道,在一个类 型的任何实例初始化以前,你应该初始化它的静态成员变量.在里C#你可以使用 静态的预置方法和静态构造函数来实现这个目的.一个类的静态构造函数是一个 与众不同的,它在所有的方法,变量或者属性访问前被执行.你可以用这个函数 来初始化静态成员变量,强制使用单件模式,或者实现其它任何在类型的实例可 用前应该完成的工作.你不能用任何的实例构造函数,其它

浅析C#静态类,静态构造函数,静态变量_C#教程

静态变量 静态变量位于栈上,它是一个全局变量,在编译期就已经生成. public class Cow { public static int count; private int id; public Cow() { id = ++count; } } 客户端创建2个Cow的实例,并打印静态变量count. static void Main(string[] args) { Console.WriteLine(Cow.count); Cow cow1 = new Cow(); Cow cow2

朋友面试被问到---静态构造函数

原文:朋友面试被问到---静态构造函数 事情是这样的 朋友是一个一年多经验的.Net开发人员 在面试新公司的时候,被面试官问到什么是"静态构造函数" 朋友回来告诉我, "构造函数还有静态的吗,看来这次面试要黄了" "对的,构造函数是有静态的啊,不过也难怪,很少人会用到,看来面试官是要看你的基础有多深啊!"   静态构造函数   我们知道,所有的静态成员,包括静态字段和静态方法,当程序运行遇到这些静态成员所在的类 在创建对象或者调用静态成员的时候,

关于C#静态构造函数的几点说明

函数|静态 静态构造函数是C#的一个新特性,其实好像很少用到.不过当我们想初始化一些静态变量的时候就需要用到它了.这个构造函数是属于类的,而不是属于哪里实例的,就是说这个构造函数只会被执行一次.也就是在创建第一个实例或引用任何静态成员之前,由.NET自动调用. class SimpleClass { // Static constructor static SimpleClass() { // } } 在使用静态构造函数的时候应该注意几点: 1.静态构造函数既没有访问修饰符,也没有参数.因为是.