zoukankan      html  css  js  c++  java
  • 第三节: 值类型与引用类型、深拷贝与浅拷贝、原型模式详解(未完)

    一. 值类型和引用类型

    1. 前言

    (1). 分类

      值类型包括:布尔类型、浮点类型(float、double、decimal、byte)、字符类型(char)、整型(int、long、short等)、枚举(entum)、结构体(struct)。

      引用类型:数组、字符串(string)、类、接口、委托(delegate)。 

    (2).内存存储

      值类型数据存放在栈stack中, 引用类型地址存放栈stack中,数据存放在堆heap中。

      值类型变量声明后,不管是否赋值,都会在在栈中分配内存空间。引用类型声明时,只在栈中分配内存,用于存放地址,并没有在堆上分配内存空间。

    (3).画图说明内存存储

      注:string是一种特殊的引用类型, 需要特别注意.

    (写博客的时候要画图 未完成)

    2.  对象的传递

    (1). 将值类型的变量赋值给另一个变量,会执行一次赋值,赋值变量包含的值。

    (2). 将引用类型的变量赋值给另一个引用类型变量,它复制的是引用对象的内存地址,在赋值后就会多个变量指向同一个引用对象实例。

    3. 参数按值传递

    (1). 对于值类型(age),传递的是该值类型实例的一个副本,因此原本的值age并没有改变。

    (2). 对于引用类型(Student stu),传递是变量stu的引用地址(即stu对象实例的内存地址)拷贝副本,因此他们操作都是同一个stu对象实例。

    4. 参数按引用类型传递

     不管是值类型还是引用类型,可以使用ref或out关键字来实现参数的按引用传递。ref或out关键字告诉编译器,方法传递的是参数地址,而非参数本身。在按引用传递时,方法的定义和调用都必须显式的使用ref或out关键字,不可以省略,否则会引起编译错误。

    5. string和其它引用类型的区别

    (1). 在string字符串,一开始s1地址指向是ypf,因为s2=s1,所以s2地址也同样指向ypf;当s1再次赋值lmr时,堆中就会开辟出数据lmr,而且ypf没有消失,没有被覆盖。s1地址就指向lmr,s2地址还是原来的ypf。

    (2). 在引用类型数组上,一开始arry1和arry2的地址都指向{1,2,3},当给arry1进行数据更改时,由于是引用类型,所以在{1,2,3}上面进行更改,就会对arry2进行覆盖。

    6. 拆箱和装箱

     装箱是值类型向引用类型转换时发生的,拆箱是引用类型向值类型转换时发生的。装箱是隐式的,拆箱是显式的

    7. 总结

    (1). 值类型有更好的效率,但不支持多态,适合用作存储数据的载体。而引用类型支持多态,适合用于定义程序的行为。

    (2). 引用类型可以派生新的类型,而值类型不能。

    二. 深拷贝和浅拷贝

    1. 浅拷贝

     创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是值类型和string类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址(string类型除外),所以修改其中一个对象,就会影响到另一个对象。

    2. 深拷贝

     将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象和原对象的修改不会相互影响.

    3. 二者区别

     最根本的区别在于是否真正获取一个对象的复制实体,而不是引用,假设B复制了A,修改A的时候,看B是否发生变化:

    (1).如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)

    (2).如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)

    简单的来说:

     如果拷贝的时候共享被引用的对象就是浅拷贝,如果被引用的对象也拷贝一份出来就是深拷贝。(深拷贝就是说重新new一个对象,然后把之前的那个对象的属性值在重新赋值给这个用户)

    4. .Net中实现

    (1).浅拷贝通过MemberwiseClone()方法实现.

    (2).深拷贝可以通过流的方式和反射的方式来实现,其中流的方式类前必须加 [Serializable], 反射的方式需要考虑的问题很多,嵌套以及各种类型, 此处提供的方法并不完善.

    5. 经过测试得出来一个结论

    (1).对于浅拷贝:所有值类型和string这个引用类型修改其中一个对象的值,不相互影响; 除了string以外的引用类型都相互影响; 类属于引用类型,修改类中的一个属性值,被拷贝的另一个对象的属性值也会发生变化(与类中的属性值是什么类型没有关系).

    (2).对于深拷贝:无论是值类型还是引用类型, 修改其中一个对象的值都不会相互影响。

    三. 原型模式详解

    1. 背景

     在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。

    2. 定义和特点

     定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。

    3. 具体实现

    (1). 模式结构

     A. 抽象原型类:规定了具体原型对象必须实现的接口,eg:.Net 中的ICloneable。

     B. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。

     C. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

    结构图如下:

     

    (2). 使用场景

     有一块视频,我需要1个一模一样的,并且我还需要1个除了路径不同其它都相同的视频,这个时候可以使用原型模式哦。

    (3). 代码实操

    4. 使用场景

    (1). 对象之间相同或相似,即只是个别的几个属性不同的时候。

    (2). 对象的创建过程比较麻烦,但复制比较简单的时候。

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    hdu (欧拉函数+容斥原理) GCD
    UVA 11624 Fire!
    drf框架之跨域问题的解决与缓存问题
    drf框架之分页器的用法
    DRF框架之 用户角色权限与访问频率的权限设置
    DRF框架之认证组件用法(第四天)
    DRF框架之视图方法的几个封装好的模块介绍(第三天)
    DRF框架之 serializers 序列化组件
    DRF框架简介(第一天)
    BBS(第三天) 如何吧用户上传的图片文件保存到本地
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/13460263.html
Copyright © 2011-2022 走看看