讨论Struct与Class之前,我们先来看一个概念:Value Type(值类型),Reference Type(引用类型):

1. 值类型的变量直接包含他们的数据,对于值类型都有他们自己的数据副本,因此对一个变量操作不可能影响另一个变量;

2. 引用类型的变量存储对他们的数据引用,因此后者称为对象,因此对一个变量操作可能影响另一个变量所引用的对象。

这就是我们之前博客中提到的深拷贝与浅拷贝,博客传送《iOS 图文并茂的带你了解深拷贝与浅拷贝》,两者的本质区别在于:深拷贝就是内容拷贝,浅拷贝就是指针拷贝

A. 是否开启新的内存地址

B. 是否影响内存地址的引用计数

讨论Struct与Class之前,我们先做好准备工作,首先分别创建一个Struct:【SNode】 与 Class:【CNode】

  1. struct SNode {
  2. var Data: Int?
  3. }
  1. class CNode {
  2. var Data: Int?
  3. }

下面我们通过代码来理解两者都有哪些异同:

1、property初始化的不同

  1. let snode = SNode(Data: ) // struct可直接在构造函数中初始化property
  2. print("snode.data:\(String(describing: snode.Data))")
  3.  
  4. let cnode = CNode() // class不可直接在构造函数中初始化property
    cnode.Data =
    print("cnode.data:\(String(describing: cnode.Data))")

打印结果:

  1. snode.data:Optional()
  2. cnode.data:Optional()

主要的差別就是 class 在初始化时不能直接把 property 放在 默认的constructor 的参数里,而是需要自己创建一个带参数的constructor, 如:

  1. class CNode {
  2. var Data: Int?
  3.  
  4. init(data: Int) {
  5. self.Data = data
  6. }
  7. }
  1. let cnode = CNode.init(data: )

2、变量赋值方式不同(深浅copy)

  1. // struct
    let snode = SNode(Data: )
  2. var snode1 = snode
  3. snode1.Data =
  4. print("snode.data:\(String(describing: snode.Data))\n snode1.data:\(String(describing: snode1.Data))")

打印结果:

  1. snode.data:Optional()
  2. snode1.data:Optional()

说明:struct 赋值“=”的时候,会copy一份完整相同的內容给另一個变量 --> 【开辟了新的内存地址】

  1. // class
  2. let cnode = CNode()
  3. cnode.Data =
  4. let cnode1 = cnode
  5. cnode1.Data =
  6. print("cnode.data:\(String(describing: cnode.Data))\n cnode1.data:\(String(describing: cnode.Data))")

打印结果:

  1. cnode.data:
  2. cnode1.data:

说明:class 赋值“=”的时候,不会copy一份完整的内容给另一個变量,只是增加了原变量内存地址的引用而已 --> 【没有开辟了新的内存地址】

3、immutable 变量

Swift 语言的特色之一就是可变动内容和不可变内容用 var 和 let 來甄别,如果初始为let的变量再去修改会发生编译错误。

struct也遵循这一特性

class不存在这样的问题:从上面的赋值代码能很清楚的看出来。

4、mutating function

  1. struct SNode {
  2. var Data: Int
  3. }
  4.  
  5. extension SNode {
  6. mutating func changeData(vaule: Int) {
  7. self.Data = vaule
  8. }
  9. }
  1. class CNode {
  2. var Data: Int =
  3. }
  4.  
  5. extension CNode {
  6. func changeData(vaule: Int) {
  7. self.Data = vaule
  8. }
  9. }

说明:struct 和 class 的差別是 struct 的 function 要去改变 property 的值的时候要加上 mutating,而 class 不用。

5、继承

struct不能继承,class可以继承。

6、struct比class更“轻量级”

struct分配在栈中,class分配在堆中。

题外话:Swift 把 Struct 作为数据模型的注意事项

优点:

1、安全性:

  1. 因为 Struct 是用值类型传递的,它们没有引用计数。

2、内存:

  1. 由于他们没有引用数,他们不会因为循环引用导致内存泄漏。

3、速度:

  1. 值类型通常来说是以栈的形式分配的,而不是用堆。因此他们比 Class 要快很多! (http://stackoverflow.com/a/24243626/596821)

4、拷贝:

  1. Objective-C 里拷贝一个对象,你必须选用正确的拷贝类型(深拷贝、浅拷贝),而值类型的拷贝则非常轻松!

5、线程安全

  1. 值类型是自动线程安全的。无论你从哪个线程去访问你的 Struct ,都非常简单。

缺点:

1、Objective-C

  1. 当你的项目的代码是 Swift Objective-C 混合开发时,你会发现在 Objective-C 的代码里无法调用 Swift Struct。因为要在 Objective-C 里调用 Swift 代码的话,对象需要继承于 NSObject
    Struct 不是 Objective-C 的好朋友。

2、继承

  1. Struct 不能相互继承。

3、NSUserDefaults

  1. Struct 不能被序列化成 NSData 对象。

所以:如果模型较小,并且无需继承、无需储存到 NSUserDefault 或者无需 Objective-C 使用时,建议使用 Struct。

知识延伸:为什么访问struct比class快?

“堆”和“栈”并不是数据结构上的Heap跟Stack,而是程序运行中的不同内存空间。栈是程序启动的时候,系统事先分配的,使用过程中,系统不干预;堆是用的时候才向系统申请的,用完了需要交还,这个申请和交还的过程开销相对就比较大了。

栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的速度快。

从两方面来考虑:

1.分配和释放:堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,而栈却不需要这些。

2.访问时间:访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。

Swift 浅谈Struct与Class的更多相关文章

  1. 浅谈Swift语法

    Apple 在2014年6月的WWDC公布了一款新型的开发语言,很多美国程序猿的价值观貌似和我们非常大的不同,在公布的时候我们能够听到,场下的欢呼声是接连不断的.假设换作我们,特别是像有Objecti ...

  2. 浅谈 Swift 2 中的 Objective-C 指针

    浅谈 Swift 2 中的 Objective-C 指针 2015-09-07  499 文章目录 1. 在 Swift 中读 C 指针 2. 在 Swift 中创建 C 指针 3. 总结 作者:Ja ...

  3. 浅谈Hybrid技术的设计与实现第三弹——落地篇

    前言 接上文:(阅读本文前,建议阅读前两篇文章先) 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 根据之前的介绍,大家对前端与Native的交互应该有一些简单的认识了,很多 ...

  4. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  5. 浅谈c语言结构体

    对于很多非计算机专业来说,c语言课程基本上指针都不怎么讲,更别说后面的结构体了.这造成很多学生对结构体的不熟悉.这里我就浅谈一下我对结构体的认识. 结构体,就是我们自己定义出一种新的类型,定义好之后, ...

  6. 浅谈 Linux 内核无线子系统

    浅谈 Linux 内核无线子系统 本文目录 1. 全局概览 2. 模块间接口 3. 数据路径与管理路径 4. 数据包是如何被发送? 5. 谈谈管理路径 6. 数据包又是如何被接收? 7. 总结一下 L ...

  7. 【架构】浅谈web网站架构演变过程

    浅谈web网站架构演变过程   前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变.   该系统具备的功能:   用户模块:用户注册和管理 商品模块:商品展示和管 ...

  8. 浅谈C中的malloc和free

    转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...

  9. [技术]浅谈OI中矩阵快速幂的用法

    前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...

随机推荐

  1. leetcode腾讯精选练习之最长公共前缀(九)

    最长公共前缀 题目 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower"," ...

  2. gulp自动化添加版本号并修改为参数格式

    问题: 当我们修改js和css文件时往往需要清除浏览器的缓存,否则有些效果就看不到更新过后的. 通过对js,css文件内容进行hash运算,生成一个文件的唯一hash字符串(如果文件修改则hash号会 ...

  3. sqlalchemy 入门

    ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上. 在Python中,最有名的ORM框架是SQLAlchemy. # 导入: from sqlalche ...

  4. 一.Memcached企业服务

    1.Memcached是什么,有什么作用?            Memcached是一个开源的.高性能的内存缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思.          ...

  5. MySQL 基础知识梳理

    MySQL 的安装方式有多种,但是对于不同场景,会有最适合该场景的 MySQL 安装方式,下面就介绍一下 MySQL 常见的安装方法,包括 rpm 安装,yum 安装,通用二进制安装以及源码编译安装, ...

  6. Java和Mysql中的数据类型

    1.mysql中的基本类型 1.整数: tinyint:1个字节   -128~127 smallint: 2个字节  -32768~32767 int :  4个字节 bigint:  8个字节 2 ...

  7. [原]CreateFile中的dwShareMode

    原 总结 API  一直对CreateFile的参数dwDesiredAccess和dwShareMode有什么不同不是很清楚,今天重读 windows核心编程的时候终于豁然开朗了. 真是书读百遍,其 ...

  8. 897A. Scarborough Fair# 斯卡布罗集市(模拟)

    题目出处:http://codeforces.com/problemset/problem/897/A 题目大意:将某个范围内的某个字符换成另外一个字符 #include<iostream> ...

  9. POJ 3617 Best Cow Line 字典序最小

    #include<cstdio> #include<iostream> #include<algorithm> #include<queue> #inc ...

  10. 洛谷-P3919-可持久化数组

    题目传送门 sol:在洛谷上看到一种dfs + 离线的方法,可以解决大部分可持久化问题.把依赖关系看成边,然后建树.这样本来要解决的多个版本只要在一个版本上进行修改就好了. 离线 + dfs #inc ...