title: 20. 所有权 III 保留所有权 tags: cairo starknet ownership preserve WTF Cairo极简教程: 20. 所有权 III 保留所有权 我最近在学 ,巩固一下细节,也写一个 ,供小白们使用。教程基于 版本。 推特:@0xAAScience|@WTFAcademy WTF Academy 社群:Discord|微信群|官网 wtf.academy 所有代码和教程开源在 github: github.com/WTFAcademy/WTF-Cairo 在 Cairo 中,当数据从一个变量分配到另一个变量或作为函数参数传递时,该数据的所有权会被转移。然而,有时我们希望能够操作数据但又保留其所有权。本章将探讨几种实现此目标的方法。
title: 20. 所有权 III 保留所有权 tags: - cairo - starknet - ownership - preserve
我最近在学cairo-lang,巩固一下细节,也写一个WTF Cairo极简教程,供小白们使用。教程基于cairo 2.2.0版本。
WTF Academy 社群:Discord|微信群|官网 wtf.academy
所有代码和教程开源在 github: github.com/WTFAcademy/WTF-Cairo
在 Cairo 中,当数据从一个变量分配到另一个变量或作为函数参数传递时,该数据的所有权会被转移。然而,有时我们希望能够操作数据但又保留其所有权。本章将探讨几种实现此目标的方法。
你可以设计一个函数,让它将所有权返回给原变量。示例:
use array::ArrayTrait; // 示例函数,移动然后返回所有权 fn return_function(){ let mut x = ArrayTrait::<felt252>::new(); // x 进入作用域 x = return_ownership(x); // 返回 x 的值的所有权 let y = x; // 这行代码有效 } // 返回所有权的函数 fn return_ownership(some_array: Array<felt252>) -> Array<felt252> { some_array }
虽然这种方法允许原变量重新获得所有权,但它需要你自己编写返回值,从而增加了代码的复杂性。
Copy 特性如之前章节所述,如果一个类型实现了 Copy 特性,将其赋值给新变量或传递给函数时,将传递该值的副本,而不会转移所有权。
#[derive(Copy, Drop)] struct Point { x: u128, y: u128, } // 示例,Point 结构体实现了 Copy 特性 fn copy_struct(){ let p1 = Point { x: 5, y: 10 }; let p2 = p1; let p3 = p1; }
但请注意,Array 和 Dictionary 类型不能实现 Copy 特性。
Cairo 允许你使用 clone() 方法手动创建一个变量的深复制(deep copy)。
fn clone_example(){ let x = ArrayTrait::<felt252>::new(); // x 进入作用域 let y = x.clone(); // 深度复制 x 并绑定到 y let z = x; // 这有效 }
clone() 的缺点是深度复制一个变量可能会消耗大量的计算资源和 gas。
在 Cairo 中,你可以使用 ref 关键字创建一个值的可变引用(mutable reference)。这个引用在函数结束时会隐式返回,将所有权返回给调用上下文。
fn reference_example(){ let mut x = ArrayTrait::<felt252>::new(); // x 进入作用域 use_reference(ref x); // 将 x 的可变引用传递给函数 let y = x; // 这有效 } fn use_reference(ref some_array: Array<felt252>) { }
请注意,只有可变变量才可以使用 ref 关键字作为引用传递。我们将在下一章更深入地探讨这个话题。
Cairo 中的快照(snapshot)为某个时间点上的值提供了一个不可变的视图。当一个函数接受一个快照作为参数时,它并不接管底层值的所有权。你可以使用快照操作符 @ 创建快照:
fn snapshot_example(){ let x = ArrayTrait::<felt252>::new(); // x 进入作用域 use_snapshot(@x); // 将 x 的快照传递给函数 let y = x; // 这有效 } fn use_snapshot(some_array: @Array<felt252>) { }
我们将在第22章更深入地探讨快照。
在本章中,我们学习了几种在 Cairo 中保留所有权的情况下操纵数据的实用方法。掌握他们会让你写出更好的 Cairo 合约。