Swift - 37 - 值类型和引用类型的简单理解

//: Playground - noun: a place where people can play

import UIKit

// 值类型:指的是当一个变量赋值给另外一个变量的时候, 是copy一个副本
// 两个变量之间互不影响, 也就是说, 另外一个变量的值改变, 不会影响到另外一个变量
// 也就是传的只是一个值, 不是一个引用(地址)
var a = 0
var b = a
b = 2
a

// 闭包和函数都是引用类型
// 引用类型:指的是当引用类型变量赋值给另外一个变量的时候, 其实两个变量指的都是同一个内容
// 当其中一个变量修改了这个内容, 另外一个变量也会跟着改变
func calcTotalMiles(todayMiles: Int) -> () -> Int
{
    var totalMiles = 0
    return {
        totalMiles += todayMiles;       // 这个闭包用到了Capturing Values
        return totalMiles
    }
}

var dailyTwoMiles = calcTotalMiles(2)
dailyTwoMiles()
dailyTwoMiles()

var myPlan = dailyTwoMiles
myPlan()
myPlan()

/*
同学A的理解:
var totalMiles = 0 这句是处在 calcTotalMiles 函数中。
而你说的每次调用,调用的并不是 calcTotalMiles 这个函数,
而是 calcTotalMiles 这个函数的返回值,也就是另一个函数。
返回的函数被命名为 dailyTwoMiles 或者 dailyThreeMiles,
返回函数的内容是闭包内容:{totalMiles += todayMiles; return totalMiles; },
其中并没有对 totalMiles 重置的语句,所以totalMiles不会被重置。
那么问题来了,totalMiles 什么时候被重置。
很简单,var totalMiles = 0 处在 calcTotalMiles 函数中,
当然是 calcTotalMiles 被调用时会被重置,
也就是 
var dailyTwoMiles = calcTotalMiles(2) 和 
var dailyThreeMiles = calcTotalMiles(3) 
这两句在运行时会重置 titalMiles.

同学B的理解:
这里的关键是:calcTotalMiles返回了一个函数,这个函数以闭包的形式返回,我们没有给他起名,
这里姑且叫他resultFunction。要注意,这个resultFunction和calcTotalMiles不是一个东西,
resultFunction是calcTotalMiles的一个结果!
仔细看这个resultFunction函数体内,涉及的两个变量:totalMiles和todayMiles,
都没有在resultFunction里定义。那resultFunction是怎么拿到这个值的呢?
这个过程是swift使用一种称为Capturing Values的方式感知到的。与此同时,一点儿没有错,这将产生内存方面的问题。
在这里,你可以理解成,我们给calcTotalMiles传入一个参数,返回了一个函数resultFunction,
之后执行calcTotalMiles所使用的栈空间并没有被释放,因为产生的resultFunction还在使用(或者是拥有)调用者calcTotalMiles的内容。

我个人的理解是:
由于calcTotalMiles的返回值是resultFunction, 而resultFunction又引用着calcTotalMiles中的变量, 
所以calcTotalMiles执行完之后并没有被销毁, 还保留在内存中...
所以当resultFunction再次调用的时候所拿到的totalMiles还没有被初始化..就会继续累加...
*/

// ps: 在实际中, 很少用到函数和闭包是引用类型这种情况, 这里仅仅作为了解...

  

posted @ 2016-01-31 15:20  Rinpe  阅读(389)  评论(0编辑  收藏  举报