返回

多角度透析浅拷贝与深拷贝,从底层理解编程本质

前端

深浅拷贝与深拷贝的含义

深拷贝 :创建一个新对象,并将原始对象的所有属性值都复制到新对象中,即使这些属性值是对象。这意味着新对象与原始对象完全独立,对新对象的任何更改都不会影响原始对象。

浅拷贝 :创建一个新对象,并将原始对象的所有属性值复制到新对象中,但不复制嵌套对象。这意味着新对象与原始对象共享对嵌套对象的引用,对新对象中嵌套对象的任何更改都会影响原始对象。

深浅拷贝与深拷贝的比较

特征 深拷贝 浅拷贝
复制方式 创建新对象并复制所有属性值,包括嵌套对象 创建新对象并复制所有属性值,但不复制嵌套对象
对象独立性 新对象与原始对象完全独立 新对象与原始对象共享对嵌套对象的引用
对嵌套对象的更改 对新对象中嵌套对象的任何更改都不会影响原始对象 对新对象中嵌套对象的任何更改都会影响原始对象
性能 由于需要复制所有属性值,因此性能较差 由于只需复制属性值,因此性能较好

深浅拷贝与深拷贝的应用场景

深拷贝和浅拷贝在不同的场景中都有其独特的应用价值。

深拷贝的应用场景:

  • 当需要创建一个与原始对象完全独立的新对象时,例如,当需要将一个对象传递给另一个函数或线程时。
  • 当需要对一个对象进行修改,但又不希望影响原始对象时,例如,当需要对一个对象进行排序或过滤时。
  • 当需要将一个对象存储到数据库或文件中时,例如,当需要将一个对象序列化为 JSON 或 XML 时。

浅拷贝的应用场景:

  • 当需要创建一个与原始对象共享对嵌套对象的引用的新对象时,例如,当需要在一个对象中存储对另一个对象的引用时。
  • 当需要对一个对象进行修改,并且希望这些修改也影响原始对象时,例如,当需要对一个对象进行编辑时。
  • 当需要将一个对象传递给另一个函数或线程时,并且不需要对该对象进行修改时,例如,当需要将一个对象作为参数传递给一个函数时。

深浅拷贝与深拷贝的实现

在不同的编程语言中,深拷贝和浅拷贝的实现方式可能有所不同。

JavaScript 中的深拷贝:

const deepCopy = (obj) => {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(deepCopy);
  }

  const newObj = {};
  for (const key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
};

Python 中的深拷贝:

import copy

def deep_copy(obj):
  return copy.deepcopy(obj)

Java 中的深拷贝:

import java.util.HashMap;
import java.util.Map;

public class DeepCopy {

  public static <T> T deepCopy(T obj) {
    if (obj == null) {
      return null;
    }

    if (obj instanceof Map) {
      Map<Object, Object> map = (Map<Object, Object>) obj;
      Map<Object, Object> newMap = new HashMap<>();
      for (Map.Entry<Object, Object> entry : map.entrySet()) {
        newMap.put(deepCopy(entry.getKey()), deepCopy(entry.getValue()));
      }
      return (T) newMap;
    }

    if (obj instanceof List) {
      List<Object> list = (List<Object>) obj;
      List<Object> newList = new ArrayList<>();
      for (Object item : list) {
        newList.add(deepCopy(item));
      }
      return (T) newList;
    }

    return obj;
  }
}

C++ 中的深拷贝:

#include <iostream>
#include <vector>
#include <map>

using namespace std;

class MyClass {
public:
  int a;
  string b;
  vector<int> c;
  map<string, string> d;

  MyClass(int a, string b, vector<int> c, map<string, string> d) :
    a(a), b(b), c(c), d(d) {}

  MyClass(const MyClass& other) {
    a = other.a;
    b = other.b;
    c = other.c;
    d = other.d;
  }
};

MyClass deepCopy(const MyClass& obj) {
  return MyClass(obj);
}

int main() {
  MyClass obj1(1, "hello", {1, 2, 3}, {{"key1", "value1"}, {"key2", "value2"}});
  MyClass obj2 = deepCopy(obj1);

  obj2.a = 2;
  obj2.b = "world";
  obj2.c[0] = 4;
  obj2.d["key1"] = "new value1";

  cout << "obj1: " << obj1.a << ", " << obj1.b << ", " << obj1.c[0] << ", " << obj1.d["key1"] << endl;
  cout << "obj2: " << obj2.a << ", " << obj2.b << ", " << obj2.c[0] << ", " << obj2.d["key1"] << endl;

  return 0;
}