美文网首页
值类型和引用类型

值类型和引用类型

作者: 周一不上班 | 来源:发表于2018-05-29 18:47 被阅读14次
  • [值类型和引用类型]
    • [什么是值类型(value type)和引用类型(reference type)]
    • [两者有什么不同]
    • [请在保证安全的情况下修改变量值]
    • [如何选择]
    • [c++类型行为的不一致性]
    • [ 参考文章]

变量类型可以帮助开发者理清程序的数据流,以写出更健壮的代码。本文通过对swift语言中的两种变量类型的介绍,来说明哪些情况下适合使用value/reference type。阅读本文不需要对swift有深入了解,当然熟悉swift编程对理解本文会有帮助。

什么是值类型(value type)和引用类型(reference type)

在swift中,一个类型要么是value type, 要么是reference type。value type指每一个变量在内存中都有单独的一份数据拷贝。reference type指数据在内存中只有一份拷贝,多个变量共享它的值。和c++中类型的使用方式不同,swift中类型的属性(value/reference)是由类型本身决定的,作为语言标准给出,稍后本文会再做介绍。

比如c++中,

#include <iostream>
int main() {
    int a = 1;
    int &b = a;    //c++中的引用可以使用在所有的类型上
    b = 2;
    printf("a = %d, b = %d\n", a, b);    //输出结果为:a = 2, b = 2
}

两者有什么不同

辨别value type,最基本和最有效的方法是观察它的拷贝行为--赋值、初始化、参数传递等带来的影响,即通过内存数据拷贝 创建 一个独立的实例(instance)。

// Value type example
struct S { var data: Int = -1 }
var a = S()
var b = a                        // a is copied to b
a.data = 42                        // Changes a, not b
println("\(a.data), \(b.data)")    // prints "42, -1"

拷贝引用则不同,它的行为类似于创建了一个指针,原来在内存中的数据依然保持一份拷贝。因而改变其中某一个变量的值也会影响其他变量,即产生副作用。

// Reference type example
class C { var data: Int = -1 }
var x = C()                      // 建立一个对象的引用x
var y = x                        // 建立对象的另一个引用y
x.data = 42                        // changes the instance referred to by x (and y)
println("\(x.data), \(y.data)")    // prints "42, 42"

可以看出这个例子和之前c++引用产生了同样的效果。

请在保证安全的情况下修改变量值

开发软件,其中最重要的要求(之一)是程序的正确性,一种保证是来自于编程语言本身,另一种当然是来自程序员。那么程序员在写代码的过程中如何选择使用的类型呢?value type和reference type相比较,选择使用value type可以使你的程序直观上更加符合逻辑。如果所有的变量在内存中都有自己单独的一块区域,你就大可不必担心程序的其他部分在无意中修改这些变量的值。这在多线程环境中尤其重要,因为不同的线程会同时修改变量的值。如果变量是reference类型就十分危险,这使你的程序出现不可预期的结果,调试起来也非常困难。

更理想的一种情况是,你声明和使用的变量是只读(不可写)的,就不会出现数据不一致的情况发生。实际上,在没有变量值改动的程序中,变量是type的或者reference的对程序的行为没有任何影响。这时候reference内存占用少,当然是优先使用reference。

如何选择

使用value type,当:

  • 你想要变量之间的赋值隐含数据拷贝,使变量之间的状态完全独立。
  • 代码中的数据操作分布在多个进程。

使用reference type,当:

  • 创建共享和允许修改的状态。

很多人其实有一种对编程语言的误解,认为在语言层面约束越少的语言越好,这样就可以很容易实现想要的功能。但是灵活性带来的坏处更加容易被人忽视。交给程序员处理的事情越多,导致写出来的代码更加容易产生bug,代码可阅读性大大降低,同时增加重构的难度。

而swift在这方面给出了比较严格的限制,在swift中,struct, Array, String, 和 Dictionary 都是value type,它们的行为就像c语言中的int,你几乎不用做任何额外的工作,比如为了防止代码的其余部分对数据进行修改而显式地为变量分配额外的内存空间,这些繁琐的过程都会因为swift中变量的value type的属性,而交给编译器去做。更加重要的是,你可以很放心的将变量的数据拷贝交给其他进程进行操作而不用担心同步问题。这些语言层面的约束都是为了程序员可以写出可预测的代码。作为对比,下文介绍c++是怎么做的。

c++类型行为的不一致性

碰巧在微信中看到的一篇文章:C++ 之 stl::string 写时拷贝导致的问题。c++在语言标准上允许不同的数据拷贝机制,联系到本文的概念,即c++中的类型是value type还是reference type取决于编译器的实现。当语言标准容忍实现的灵活性时,虽然多数时候是为了优化性能,但是带来的问题似乎更加严重--导致程序的运行结果不同于预期。

参考文章

  1. Value and Reference Types
  2. Why java has "String" type and not "string"? - Stack Overflow
  3. If immutable objects are good, why do people keep creating mutable objects?
  4. C++之stl::string写时拷贝导致的问题

相关文章

  • 面试

    值类型和引用类型 值类型和引用类型的区别是值类型直接存储其值,而引用类型存储对值的引用。这两种类型存储在内存的不同...

  • 慕课网《前端JavaScript基础面试技巧》学习笔记

    变量类型 值类型和引用类型 值类型只能存储一个值 值类型复制就是值类型本身 引用类型复制只是复制引用类型的指针 引...

  • 基本类型值和引用类型值

    JavaScript变量可以用来保存两种类型的值:基本类型值和引用类型值。 *引用类型包括: 基本类型值和引用类型...

  • 对象

    1.对象分为值类型和引用类型 值类型(不是对象) 引用类型(都是对象) 类型的判断值类型判断用typeof引用类型...

  • 01_JS面向对象

    知识点 数据类型 值类型和引用类型 值类型和引用类型的特征 值类型和引用类型做参数 对象的动态特性 给对象动态添加...

  • C# 装箱,拆箱,向上转型,向下转型

    c#中,数据类型分为值类型和引用类型,装箱和拆箱属于值类型和引用类型间的转换操作。 装箱:值类型向引用类...

  • 第一部分:C#语言基础

    第1章 C#类型基础 C#中的两种类型:值类型和引用类型 1.1 值类型和引用类型 值类型包括了结构和枚举,引用类...

  • c#面向对象11--值类型和引用类型/序列化和反序列化

    值类型和引用类型 值类型:int double char enum bool decimal struct引用类型...

  • C#值类型和引用类型

    值类型和引用类型的区别(小结)相同点:引用类型可以实现接口,值类型当中的结构体也可以实现接口;引用类型和值类型都继...

  • 引用类型对象拷贝

    1.引用类型有哪些?非引用类型有哪些 JavaScript数据分为基本类型值和引用类型值基本类型值(数值、布尔值、...

网友评论

      本文标题:值类型和引用类型

      本文链接:https://www.haomeiwen.com/subject/lfgajftx.html