rust函数指针和闭包异同探索随笔

2024-06-20 21:28

本文主要是介绍rust函数指针和闭包异同探索随笔,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

//rust需要在编译时确定某个类型的值究竟会占据多少内存,而且同一类型的所有值都必须使用相同大小的内存,否则编译无法进行。

//对于DST动态大小类型在编译器期间无法得知其确切大小,所以直接定义此种类型的变量,rust编译无法通过!

//那么如何应对?基本上采用:引用、智能指针、impl等方式即可解决。

//rust函数是一等公民,当然可以作为参数传递存储返回。

//rust函数指针fn是rust本身具有的数据类型之一,而闭包是trait,确切说是三个trait: Fn/FnMut/FnOnce.

//因为rust函数指针impl了全部三个闭包trait, 我们总是可以把函数指针用作实参传递给一个声明接受闭包的函数。

//rust函数指针可以指向“非捕获型闭包” , 我的理解:在rust中“捕获型闭包”因为需要记录被捕获的值,所以需要创建一个结构体记录之!所以“捕获型闭包”实际上是一个结构体;

//而“非捕获型闭包”实际上就是一个函数,因为他需要的值都是通过调用传参获得,不需要记录什么,所以只需要一个函数指针记录执行入口即可。

//切记:闭包可以捕获外部变量,而函数不可以。

//当然以上是我查阅资料和代码试验后的个人理解,

//水平有限,若有谬误,希望指正。

//详细解释请仔细阅读rust编译报错提示信息即可。

//rust函数指针例子

fn add_one(x:i32) -> i32 {

    x+1

}

//case1: 把函数指针用作函数参数,传参, 编译通过。

fn do_twice(f: fn(i32)->i32, arg:i32)->i32{

    f(arg) + f(arg)

}

//case2:把函数指针用作函数返回值,编译通过。

fn take_a_function_pointer() -> fn(i32)->i32 {

    add_one

}

//rust闭包例子

//Fn/FnMut/FnOnce是闭包的三个trait.

//case3: 通过trait object返回闭包,编译通过。

fn returns_closure_by_trait_object()-> Box<dyn Fn(i32)->i32> {

    Box::new(|x| x+1)

}

//case4: 编译错误:rust编译器无法获知闭包trait编译期已知大小,请使用Box或者impl.

//fn returns_closure3()->  Fn(i32)->i32 {

//    |x| x+1

//}

//case5: 把函数指针用作返回值类型,可以返回函数或非捕获型闭包,编译通过!

fn returns_closure2_by_fn_pointer() -> fn(i32)->i32 {

    |x| x+1

}

//case6: 编译错误:rust编译器无法获知闭包trait编译期已知大小,请使用泛型或者impl或者&dyn trait object.

//fn take_closure(f: Fn(i32)->i32, arg:i32) -> i32{

//    f(arg)

//}

//case7:编译通过,通过函数指针类型形参接受非捕获型闭包或函数。

fn take_fn_or_closure_by_function_pointer(f: fn(i32)->i32, arg:i32) -> i32{

    f(arg)

}

//case8:编译通过,通过闭包trait形参接受函数指针和闭包

fn take_fn_or_closure_by_closure_trait(f: impl Fn(i32)->i32, arg:i32) -> i32 {

    f(arg)

}

fn main() {

    //for case1.

    let answer = do_twice(add_one, 5);

    println!("the function pointer answer is : {}", answer);

    //for case2.

    println!("-----------------------");

    let fp = take_a_function_pointer();

    let answer2 = fp(5);

    println!("to return function pointer answer is :{}", answer2);

     //----------------------------------

     //for case3.

    let ac = returns_closure_by_trait_object();

    let answer3 = ac(5);

    println!("to return Box dyn closure answer is: {}", answer3);

    //for case5.

    println!("-----------------------");

    let acp = returns_closure2_by_fn_pointer();

    let answer3 = acp(5);

    println!("to return closure by the function pointer answer is : {}", answer3);

    //for case7.

    println!("-----------------------");

    //函数指针可以指向“非捕获型闭包”,我理解“捕获型闭包”是通过:获取所有权(包括值复制)、可变借用、不可变借用等手段而非调用传参方式获取值。打开注释,注意编译报错信息。

    let answer4 = take_fn_or_closure_by_function_pointer(|x|x+1, 5);

    println!("to take closure by function pointer answer is : {}", answer4);

    let answer5 = take_fn_or_closure_by_function_pointer(add_one, 5);

    println!("to  take function by fn pointer answer is: {}", answer5);

    //函数指针不可以指向“捕获型闭包”,编译报错。

    //let a = 5;

    //let answer6 = take_fn_or_closure_by_function_pointer(|x| x+a, 5);

    //let a_str = String::from("hello world!");

    //let answer7 = take_fn_or_closure_by_function_pointer(|x| {println!("{}",a_str); x+1}, 5);


 

    //for case8.

    println!("-----------------------");

    let answer8 = take_fn_or_closure_by_closure_trait(|x|x+1, 5);

    println!("to take a closure by the closure trait, answer is: {}", answer8);

    let answer9 = take_fn_or_closure_by_closure_trait(add_one, 5);

    println!("to take a function by the closure trait, answer is: {}", answer9);



 

}

这篇关于rust函数指针和闭包异同探索随笔的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1079302

相关文章

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释

Rust格式化输出方式总结

《Rust格式化输出方式总结》Rust提供了强大的格式化输出功能,通过std::fmt模块和相关的宏来实现,主要的输出宏包括println!和format!,它们支持多种格式化占位符,如{}、{:?}... 目录Rust格式化输出方式基本的格式化输出格式化占位符Format 特性总结Rust格式化输出方式

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Rust中的BoxT之堆上的数据与递归类型详解

《Rust中的BoxT之堆上的数据与递归类型详解》本文介绍了Rust中的BoxT类型,包括其在堆与栈之间的内存分配,性能优势,以及如何利用BoxT来实现递归类型和处理大小未知类型,通过BoxT,Rus... 目录1. Box<T> 的基础知识1.1 堆与栈的分工1.2 性能优势2.1 递归类型的问题2.2

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于