当前位置: 首页 > news >正文

大白话解析 Solidity 中的数据位置关键字 memory

一、什么是memory:

memory是 Solidity 中的一种数据位置(data location),它表示“数据是临时的,只在函数调用期间存在内存里,用完就扔”。​

你可以把它简单理解为:

​“内存条” —— 函数运行时临时放数据的地方,速度快,但数据不永久保存。”​


二、Solidity 中数据的三大“居住地”

在 Solidity 中,变量(或函数参数)并不是随便放的,它们通常住在三个地方之一:

数据位置

说明

生命周期

常见用途

是否持久化

storage

数据存在区块链的存储区(硬盘)

永久保存,直到合约销毁

状态变量(比如 uint public count;

✅ 永久

memory

数据存在内存里(RAM)

仅在函数调用期间存在,函数结束就销毁

函数参数、局部变量、临时数据

❌ 临时

calldata

类似 memory,但是更省 gas,用于外部传入的数据

仅在函数调用期间存在

外部函数的参数(比如其他合约调你时传的数据)

❌ 临时


三、那 memory到底是干嘛用的?

想象你在玩电脑:

  • ​硬盘(storage)​​:存放你的所有文件、照片、游戏存档 —— 永久保存

  • ​内存条(memory)​​:运行游戏或软件时,临时加载一些数据到内存里,用完了就清掉,不永久保存

  • ​网络传来的临时数据(calldata)​​:就像别人临时发给你的一张纸条,你看了就扔,不存档

在 Solidity 智能合约里:

  • storage​ 就像是硬盘,用来存​​状态变量​​(比如你的余额、合约配置等),这些数据会​​永远存在链上​

  • memory​ 就像是内存条,用来放​​函数运行时临时用到的数据​​,比如:

    • 函数内部定义的临时变量

    • 传给某个内部函数的参数

  • calldata​ 是更省 gas 的数据位置,用于​​外部调用传进来的参数​


四、举个最简单的例子 🌰

看这个函数:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract MemoryExample {uint public storedData; // 这是 storage,永久保存在链上function useMemory(uint input) public pure returns (uint result) {uint temp = input * 2; // temp 是 memory(其实是隐式的),只在函数里有效result = temp;}
}

代码解析:

  • storedData是一个 ​​状态变量​​,它默认存储在 ​storage​ 中,永久保存在区块链上

  • input是函数的参数,默认情况下对于 pureview函数,它是 ​calldata​(更省 gas)

  • temp是函数内部定义的一个变量,它存放在 ​memory​(或者栈上,但你可以理解为临时内存)

🔹 虽然我们没有显式地写 memory,但 Solidity 在某些情况下会​​自动帮你选好数据位置​​。


五、什么时候需要​​显式地使用 memory?​

主要是在以下两种情况下:


情况 1:​​将数据从 storage 复制到 memory(用于读取或传递)​

因为 ​​直接操作 storage 比较贵(gas 高)​​,如果你只是​​读取数据,不想修改它​​,可以先把它复制到 memory,这样更省 gas。

✅ ​​常见用法:把 storage 变量转成 memory 传给其他函数​

function getData() public view returns (uint) {uint[] memory tempArray = myArray; // 把 storage 数组复制到 memoryreturn tempArray[0];
}

但注意:如果你有一个 ​​storage 数组或结构体​​,你想在函数里操作它但不想影响原数据,你可能需要显式用 memory拷贝一份。


情况 2:​​函数参数类型声明为 memory​

当你写一个 ​​函数,接收一个数组、字符串或结构体,并且你明确希望它只在内存里操作(而不是 storage)​​ 时,你可以显式地声明为 memory

function processData(uint[] memory numbers) public pure returns (uint sum) {for (uint i = 0; i < numbers.length; i++) {sum += numbers[i];}
}

🔹 这里的 numbers是一个数组参数,我们明确告诉 Solidity:“请把这个数组放在内存里,而不是 storage!”

这样可以:

  • 避免意外修改 storage 数据

  • 更安全

  • 在某些情况下更省 gas


六、memory vs storage vs calldata

类型

存哪里?

能修改吗?

用在什么地方?

是否永久?

Gas 成本

storage

区块链存储区(硬盘)

✅ 可修改

状态变量(比如 uint x;

✅ 永久保存

⛽️ 最贵

memory

函数运行时的内存(RAM)

✅ 可修改,但只在函数内有效

函数内部变量、临时数据、传参

❌ 临时(用完就丢)

⛽️ 中等

calldata

类似 memory,但是更省 gas,用于外部调用传入的数据

❌ 只读(不能改)

外部函数参数(比如其他合约调你时传的数组)

❌ 临时

⛽️ 最省


七、再举个实用例子:数组操作 🌟

场景:你有一个 storage 数组,你想在函数里遍历它,但不想直接操作原数组

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract ArrayExample {uint[] public myNumbers = [1, 2, 3]; // storage 数组// 读取数组内容,用 memory 来避免直接操作 storagefunction readNumbers() public view returns (uint[] memory) {uint[] memory result = myNumbers; // 从 storage 复制到 memoryreturn result;}// 接收一个 memory 数组参数,安全且省 gasfunction sumArray(uint[] memory nums) public pure returns (uint) {uint sum = 0;for (uint i = 0; i < nums.length; i++) {sum += nums[i];}return sum;}
}

🔹 在 readNumbers()中,我们把 storage 数组复制到了 memory,再返回

🔹 在 sumArray(uint[] memory nums)中,我们明确使用 memory来接收一个临时数组,避免操作 storage,更安全也更省 gas


八、总结:memory是啥?

问题

答案(大白话)

memory是什么?​

它是 Solidity 中的一种数据位置,表示数据放在“内存”里,是临时的,函数调用完就销毁

​它像什么?​

就像电脑的内存条(RAM),运行时临时存点数据,速度快但不永久

​用来干嘛?​

用来存函数内部的临时变量、传参、数组/结构体的副本等

​和 storage 有什么区别?​

storage是区块链上的硬盘,永久保存;memory是临时的内存,用完就丢

​和 calldata 有什么区别?​

calldata也是临时的,但更省 gas,通常用于外部调用传进来的数据(只读)

​什么时候用 memory?​

当你想操作临时数据、避免改 storage、或优化 gas 时


✅ 一句话终极总结:

memory就是 Solidity 中的“临时工作区”,用来放函数运行时需要用的数据,比如临时变量、传入的数组等,它只在函数调用期间存在,用完就扔,不永久保存。​

http://www.lryc.cn/news/622280.html

相关文章:

  • [激光原理与应用-284]:理论 - 波动光学 - 无线电波,无线通信的频谱
  • 人工智能与社会治理:从工具到生态的范式重构
  • 数据民主化×智能进阶化:AI+BI不可逆的决策革命已至
  • Python 高级语法与用法详解 —— 提升编程效率与代码质量
  • JUC LongAdder并发计数器设计
  • Manus AI与多语言手写识别
  • 项目生命周期
  • stream流debug
  • 源码分析mcp定义tools映射到LLM输入的过程
  • L4 级别自动驾驶 软件架构设计
  • Midjourney绘画创作入门操作
  • 二十四、Mybatis-基础操作-删除(预编译SQL)
  • 什么是可信空间的全域节点、区域节点、业务节点?
  • 基于STM32与边缘计算的工业设备异常振动预警系统设计
  • Pytest 插件使用指南:让你的测试更高效
  • 深度解读 Browser-Use:让 AI 驱动浏览器自动化成为可能
  • 如何回答研究过MQ的源码吗
  • week1-[顺序结构]大海
  • Centos7 服务管理
  • SpatialVLM和SpatialRGPT论文解读
  • ChatGPT-5(GPT-5)全面解析:一场从通用智能迈向专属智能的进化风暴,正在重塑人类与机器的协作边界
  • C#---StopWatch类
  • 【JAVA高级】实现word转pdf 实现,源码概述。深坑总结
  • 用matlab实现的svdd算法
  • 数据库(3)
  • Java学习day_12之面向对象进阶(抽象类接口内部类)
  • 【Golang】:流程控制语句
  • Java 正则表达式的使用方法
  • 开源长期记忆 短期记忆 框架调研对比19999字
  • 如何写好大模型的提示词prompt