Lua | 每日一练 (5)

💢欢迎来到张胤尘的技术站

💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥

文章目录

Lua | 每日一练 (5)

题目

lua 中深拷贝和浅拷贝的区别?如何实现深拷贝?

参考答案

深拷贝和浅拷贝是编程中常见的两种数据复制方式,它们的区别主要在于对数据结构中嵌套内容的处理方式。

下面针对这两种拷贝方式进行详细的梳理。

浅拷贝

浅拷贝是指创建一个新的对象,然后将原对象中的内容根据不同的类型选择不同的处理方式。

  • 如果内容是简单数据类型(如数字、字符串、布尔值),则直接复制值;
  • 如果内容是复杂数据类型(如对象、数组、表等),则只复制其引用(即内存地址),而不是复制其内部结构。

下面给出代码示例,如下所示:

lua 复制代码
local original = { a = 1, b = { c = 2 } }
local shallowCopy = {}

for k, v in pairs(original) do
    shallowCopy[k] = v
end

-- 修改嵌套表
shallowCopy.b.c = 3
print(original.b.c) -- 3

深拷贝

深拷贝是指创建一个新的对象,并递归地复制原对象中的所有内容,包括嵌套的复杂数据类型。深拷贝会创建完全独立的副本,修改副本中的内容不会影响原对象。

lua 标准库中没有直接提供深拷贝功能,但可以通过自己编写递归函数实现。例如:

lua 复制代码
local function deepCopy(original)
    -- 检查是否为表
    if type(original) ~= "table" then
        return original
    end

    -- 创建新表
    local copy = {}
    -- 遍历原表的所有键值对
    for k, v in pairs(original) do
        -- 递归拷贝值
        copy[deepCopy(k)] = deepCopy(v)
    end
    return copy
end

local original = { a = 1, b = { c = 2, d = { e = 3 } } }
local deepCopyTable = deepCopy(original)

deepCopyTable.b.c = 10
print(original.b.c)      -- 2
print(deepCopyTable.b.c) -- 10

还有一点需要注意的是,在处理递归时如果表中存在循环引用(例如 t = {a = 1}; t.b = t),上述简单实现会导致无限递归。

为了避免上述的这种情况,可以在实现中加入一个"已拷贝表"的映射(seen 表),记录已经拷贝过的表,避免重复拷贝。另外如果表有元表,深拷贝时也需要考虑是否需要拷贝元表,以及如何处理元表中的引用。

下面给出一个改进后实现深拷贝的版本,如下所示:

lua 复制代码
local function deepCopy(original, seen)
    -- 检查是否为表
    if type(original) ~= "table" then
        return original
    end

    -- 检查是否已经拷贝过
    if seen and seen[original] then
        return seen[original]
    end

    -- 创建新表
    local copy = {}

    -- 记录已经拷贝的表
    seen = seen or {}
    seen[original] = copy

    -- 遍历原表的所有键值对
    for k, v in pairs(original) do
        copy[deepCopy(k, seen)] = deepCopy(v, seen)
    end

    -- 拷贝元表
    local mt = getmetatable(original)
    if mt then
        setmetatable(copy, deepCopy(mt, seen))
    end

    return copy
end

local t = { a = 1 }
t.b = t
local copy = deepCopy(t)
print(copy.b == copy) -- true

使用场景

  • 浅拷贝:当对象的结构简单,并且不包含嵌套的复杂数据类型时可以使用浅拷贝,另外当需要快速复制对象且不介意共享嵌套内容时也适用浅拷贝。

  • 深拷贝:当对象结构复杂,例如包含嵌套的复杂数据类型时且使用过程中需要完全独立的副本,修改副本不影响原对象时需要使用深拷贝。

🌺🌺🌺撒花!

如果本文对你有帮助,就点关注或者留个👍

如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。

相关推荐
Victor3563 小时前
Redis(104)Redis的最大数据量是多少?
后端
Victor3563 小时前
Redis(105)Redis的数据类型支持哪些操作?
后端
鬼火儿10 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin10 小时前
缓存三大问题及解决方案
redis·后端·缓存
yoke菜籽10 小时前
面试150——字典树
面试·职场和发展
间彧11 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧11 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
零雲11 小时前
java面试:有了解过RocketMq架构么?详细讲解一下
java·面试·java-rocketmq
间彧11 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧11 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端