zoukankan      html  css  js  c++  java
  • 关于静态与非静态之具体总结

    花费了些功夫,差点儿相同搞明确了:

    大家会看到有些地方不停反复出现——那就是你要找的东西

    本文參考多处,详细出处就不写了。

    静态和非静态:

    字段、函数成员的声明中含static修饰符时是静态成员,否则是非静态成员(实例成员);

    数据成员能够分静态变量、非静态变量两种. 静态成员属于类,而非静态成员(实例成员)属于对象。

    对于类的数据成员来说。假设是静态的,那么他将是类的一部分,为全部实例共享,假设是非静态的。则每一个实例有一份考贝。


    类的非静态成员属于类的实例全部,每创建一个类的实例都在内存中为非静态成员开辟了一块区域。而类的静态成员属于类全部。被这个类的全部实例所共享。不管这个类创建了多少个副本,一个静态成员在内存中仅仅占有一块区域。


    假如以E.M形式訪问静态成员,E必须为类;訪问实例成员,E必须是实例。


    类的静态字段仅仅分配一个存储单元,类的每一个实例字段都有单独拷贝。
    静态函数成员中不能訪问实例成员。不能使用this;实例函数成员中能够訪问实例成员和静态成员。能够使用this。

    静态成员:静态类中的成员增加static修饰符,即是静态成员.能够直接使用类名+静态成员名訪问此静态成员,由于静态成员存在于内存,非静态成员须要实例化才会分配内存,所以静态成员不能訪问非静态的成员..由于静态成员存在于内存,所以非静态成员能够直接訪问类中静态的成员.

     
     非成静态员:全部没有加Static的成员都是非静态成员,当类被实例化之后,能够通过实例化的类名进行訪问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,由于静态成员始终驻留在内容中..


    语法上来讲,静态函数没有this指针。

    因为没有this指针,就不能通过对象来引用,仅仅能通过类名引用,
    在静态函数内部也不能引用非静态的成员变量。

    调用普通函数的时候。类实例的this指针是作为第一个參数隐式传给函数的。从这里说,普通函数是依赖于类的实例的,没有类实例就不能调用。而static函数没有this这个隐含參数。所以调用它时不用依赖类实例。也就是能够採用className::funName的方式调用。类静态函数对于全局函数来说有一个优点就是能够使用类的private和protected成员(当他获得类实例指针的时候,比方參数传入)。

    抽象的语义上来讲,静态函数的动作就是属于整个类的,不属于某个详细的对象。


    静态和非静态主要有下面区别:
    1.从存储的角度看。静态变量和方法在静态存储区分配内存,而非静态的在栈区或者堆上分配内存
    2.从作用域来讲,静态变量在其作用域范围内存在于整个程序的执行过程中,而非静态变量的作用时间也是局部的。
    3.从使用角度来讲。静态变量和方法没有this指针。仅仅能通过类名引用。
    4.对于类的数据成员来说。假设是静态的,那么他将是类的一部分,为全部实例共享,假设是非静态的,则每一个实例有一份考贝。


     一个类中也能够包括静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..

    对于类的数据成员来说,假设是静态的,那么他将是类的一部分。为全部实例共享,假设是非静态的,则每一个实例有一份考贝。

    静态成员函数仅仅有一份拷贝。而普通成员函数在每一个类对象中都有一份拷贝。

    构造函数是对类或实例进行初始化的函数成员。
    析构函数是在撤销类的实例时自己主动调用的函数成员。
    出了构造函数和析构函数不能被继承。其它全部的成员都能够被继承。

    静态构造函数:实现对一个类进行初始化的函数成员。



    实例构造函数:创建实例时,用于运行对类的实例进行初始化的函数成员。
     
     对于winApp来说,静态成员对于程序猿本身省了非常多事,并且由于静态成员驻留内存,在方法与方法之间传递共享数据的时候,所以静态成员成了我的首选..可是不要由于方便,大量使用,尤其是在内存紧张或者
     用静态方法操作一些共享值的时候.或者要写多用户系统的时候,要慎之又慎.比方:
     static int id = 0;
     sql = "select * from table where id=" + id;

     
     假设这样写的话,在单机測试的时候没有问题,可是在多人同一时候对数据进行測试的时候,就会有问题了.假如,A用户訪问他的id是20,则id的值在内存中为20,而此时B用户訪问,他的id是30,则id在内存中的值是30..A用户的id值则被更改了..假设此时你将这种方法用非静态成员来写,则不会出现这种情况..由于非静态成员是你声明的时候,实例化的时候才会分配内存..所以A用户訪问的时候,App会由于A实例化而给A用户的请求分配内存..而B用户訪问的时候也一样会由于B用户的訪问而分配内存..所以两个用户訪问的是不同的内存块..所以不会出现数据覆盖和错乱的现象...
     
    我想这种情况应该能非常好的说明静态变量和非静态成员的差别..
      
    相对于webApp而言,在winApp下使用static的时候要比webApp下考虑的因素要少的多,由于webApp本来就是一个多用户的系统,所以使用static的时候更应该小心..

    而我对static在webApp下的使用存在一个疑问,假设一个静态方法,比如:

    static string aa(string str){
     //经过一系列操作..
     return str;
    }

    或者返回一个DataSet的静态方法
    static DataSet aa(string str){
     //经过一系列操作..
     return DataSet;
    }

    这个时候,在訪问量大的时候,程序出现了并发,会不会发生错乱??我曾经的项目使用的公用函数类中使用了大量的静态方法,只是好在訪问量不大,一直没有问题..在发这个文章之前,我查找了MSDN,CSDN,搜索了一些关于静态成员的文章,可是都没有一个明白的说明..尽管,自己在项目中也測试了这么长时间也没有问题..可是总认为有这个可能发生..

    不知道大家是否在项目中碰到类似的疑惑呢?

    ?请有过这方面经验的朋友不吝赐教..


    答案:
    不说是否滥用。假设你出现冲突,说明你没有理解静态成员变量和静态方法的差别,静态方法本身仅仅是一段代码,无论怎么调用他都不会出现故障。但静态成员变量就不行了,他被全部用户共享,假设一个用户改变了他。肯定会影响到别人,这就是常说的并发冲突问题,一般来说在改动共享成员变量时要lock!


    关于静态方法和实例方法的一些误区。

    一、    静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。

     
        其实。方法都是一样的,在载入时机和占用内存上。静态方法和实例方法是一样的。在类型第一次被使用时载入。调用的速度基本上没有区别。
     
     
    二、    静态方法在堆上分配内存,实例方法在堆栈上。
     
        其实全部的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被载入到特殊的代码内存区域,这个内存区域是不可写的。
     
     
    三、    实例方法须要先创建实例才干够调用。比較麻烦。静态方法不用。比較简单。
        其实假设一个方法与他所在类型的实例无关。那么它就应该是静态的。决不会有人把它写成实例方法。

    所以全部的实例方法都与实例有关,既然与实例有关,那么创建实例就是必定的步骤,没有麻烦简单一说。实际上上你能够把全部的实例方法都写成静态的,将实例作为參数传入就可以。

        有些方法看似与所在的实例无关,如IComparer.Compare方法。但实际上每个实现这个接口的类都仅仅会负责自己类型实例的比較,这是C#1.x规范中没有泛型所带来的历史遗留问题。
        大部分静态方法是与类的实例有关的,如各种Parse方法,他做成静态的原因是他没有实例作为參数。其它的大多是出于语义或者其它目的的考虑。

     
    以下做了个简单的样例
    Code
  • 相关阅读:
    hadoop再次集群搭建(3)-如何选择相应的hadoop版本
    48. Rotate Image
    352. Data Stream as Disjoint Interval
    163. Missing Ranges
    228. Summary Ranges
    147. Insertion Sort List
    324. Wiggle Sort II
    215. Kth Largest Element in an Array
    快速排序
    280. Wiggle Sort
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7253945.html
Copyright © 2011-2022 走看看