在 MATLAB 中复制对象

2025年7月25日 | 阅读 8 分钟

引言

MATLAB 中的对象就是创建实例的类,这些实例包含数据以及将要经历的处理过程。MATLAB 有两种类型的类,即句柄类和值类,它们各自决定了该类的对象在赋值给其他变量或作为函数参数传递时的行为方式。

  • 句柄类: 句柄类的句柄代表单个数据实例。所有对该对象的引用都会看到对句柄对象所做的任何更改。这些类在需要共享资源或状态的多个函数或操作流程涉及的情况下非常实用。
  • 值类: 值类的对象就像基本类型(如 double 或 struct)一样工作。如果将值对象赋值给另一个变量,则会创建一个新对象,而您无法更改另一个值对象。

在 MATLAB 的面向对象编程中,对象在创建高效且易于组装的代码方面处于核心地位。它们通常集成到模拟、数据计算和图形用户界面设计中。

MATLAB 用途中的对象复制作用

  • 模拟: 同时执行多个线程,对同一对象的不同排列进行操作,这通常在每个系统中都不可能实现。
  • 数据分析: 通过复制数据对象来进行单独的预处理或分析来处理大型数据集。
  • 软件开发:GUI或用户自定义工具箱等场景中,必须复制对象,以便在不修改实际对象的情况下处理用户交互。
  • 数据版本控制: 在迭代更新对象时,创建副本可确保保留原始数据以进行比较或回滚。

复制复杂对象的挑战

  • 嵌套属性: 当处理包含其他对象、数组或其他动态结构作为其属性的对象、数组或其他动态结构时,在复制所有嵌套组件时应更加注意。
  • 句柄对象: 在句柄类中,当一个对象被赋值给另一个变量时,句柄本身并不会创建一个单独的副本,只有一个该对象的副本,而另一个变量指向这个副本。这种操作可能导致意想不到的更改或上下文的改变。
  • 内存限制: 克隆大型或嵌套结构在处理大量数据的应用程序中可能非常占用内存。为了避免高昂的开销,必须采用高效的复制方法。
  • 自定义复制逻辑: 某些对象需要特定的复制机制,因为它们指向其他对象;这些对象包括文件句柄、图形对象,甚至指向其他系统的对象。
  • 性能权衡: 精确复制与性能考虑之间的权衡可能很难解决,这对于需要快速结果或大型模拟模型的应用程序尤其重要。

MATLAB 中的复制类型

1. 浅复制

浅复制会创建一个新对象,但新对象不会复制与之关联的所有内容。除此之外,它还会复制数据的引用。这意味着对复制对象元素的属性所做的修改,如果指针指向共享内存,也可能改变原始副本。

  • 对象的外部结构被复制,但嵌套对象或数据保持链接。
  • 内存效率高且省时,因为不需要对对象的进行复杂搜索。
  • 当对象属性不可更改或共享是故意的。

用例和示例

  • 共享引用: 当您希望对象的副本使用相同的内存来存储数据并可能生成相同值,并且在修改时,更改应反映在所有对象副本中时,使用浅复制是很好的。
  • 轻量级复制: 在处理大型对象,而深复制涉及大量计算的情况下,浅复制可能就足够了。

示例

2. 深复制

而深复制则会调用所有内部对象和结构的复制,从而创建一个全新的对象。这减少了复制对象所做的修改以任何方式影响原始对象的情况。

  • 递归地完整复制所有嵌套对象和数据,因此是独立的。
  • 与浅复制相比,由于需要为每个嵌套结构创建新的内存空间,因此内存占用更多。
  • 在处理可修改和复杂信息时有助于分离。

用例和示例

  • 确保隔离: 当处理需要并行运行的对象时(例如在模拟中,或者不同的人不应影响他人的数据时),这是最有用的。
  • 处理自定义类: MATLAB 句柄类:当一个对象的属性发生某些更改不应影响其他对象时,有必要使用深复制。

示例

深复制和浅复制之间的区别

方面浅拷贝深拷贝
内存使用
副本的独立性共享引用和更改会影响原始对象完全独立;无共享数据
复杂度简单计算成本高

MATLAB 中复制对象的方法

1. 使用 copy 方法

句柄类具有默认的 copy 方法,允许 MATLAB 用户创建对象的可选浅复制或深复制,而无需担心性能问题。

copy 方法直接与句柄对象相关联,可以按如下方式调用

限制和最佳实践

  • copy 方法默认创建一个浅复制,这意味着如果对象链接到其他对象,则会复制链接,但数据不会被复制。
  • 它不支持深复制,并且在其自定义类实现中,深复制结构存在很大差距。

2. 在自定义类中覆盖 copy 方法

在使用和创建子类时,特别是那些从句柄类派生的类,覆盖 copy 方法的能力使用户能够完全控制复制过程。

  • 句柄类: 句柄对象是指向内存的有意义的指针。这意味着在使用复制构造函数时,大多数情况下,它只是为您提供数据的新句柄。
  • 值类: 值对象将数据与其他对象分开保存。clone 用于创建值对象的新克隆,其中所有属性都具有相同的值。

在句柄类中实现深复制

因此,深复制意味着新对象拥有依赖属性和对象的副本。

使用深复制时,请在类中提供 assignDeepCopy 实现的 copyElement 方法

3. 直接复制数据属性

在更简单的情况下,直接复制对象的属性是一种非常有效且易于采用的方法。

简单对象的手动方法

如果值类或对象具有简单数据属性,则可以手动复制数据。

  • 复杂对象: 对于嵌套对象或调用其他属性的对象,手动复制会非常容易出错或无效。
  • 动态属性: 在某些情况下,对象可能具有必须在复制时获取的动态属性或方法;否则,可能会丢失。

复制句柄类和值类

1. 句柄类

MATLAB 中的类结构是基于句柄的;那时,当您复制一个句柄对象时,您将获得内存区域的新变量名。这种指针的行为就像任何其他编程语言中的指针一样。与复制的变体相关的修改会影响原始对象,因为两者都引用内存中的同一空间。

示例

写时复制语义

MATLAB 对句柄对象使用写时复制语义。如果对象在两个引用变量之间传递,它仅在复制操作是强制性的(例如,使用 copy 方法)时才创建副本。这提高了内存管理的系统效率,但要求编写者独立模拟自定义句柄类的唯一性功能。

使用 copy 方法的示例

2. 值类

MATLAB 中的值类具有模仿数组或结构体的属性。当您复制值对象时,Numeric MATLAB 会创建一个具有与先前对象相同的属性的新对象。最后,对复制对象的更改不会反映在原始对象上,因为每个对象都有其内存分配。

  • 复制创建一个新的原始对象,与原始对象在意义上有所不同。
  • 对新实例所做的修改不会影响旧实例。
  • 适用于您想要一个不变的环境或在其他操作期间需要安全的环境。

示例

区别总结

方面句柄类值类
复制行为引用同一对象创建新的独立实例
内存使用共享直到显式复制单独的内存分配
用例共享资源,动态引用独立的实例对象