- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我用 gtk-rs 构建了一个 GTK 应用程序。当我构建主窗口时,我想使用一些动态参数,例如窗口高度。我创建了一个包含所有此类设置的结构,并希望将其用作构建 UI 的函数的输入参数:
fn main() {
let application =
gtk::Application::new(Some("id"), Default::default())
.expect("Initialization failed...");
let config = Config {width: 100., height: 100.};
application.connect_activate(|app| {
build_ui(app, config.clone());
});
// Use config further
application.run(&args().collect::<Vec<_>>());
}
#[derive(Debug, Clone)]
pub struct Config {
pub width: f64,
pub height: f64,
}
fn build_ui(application: >k::Application, config: Config) {
...
}
在调用 build_ui
时我不能使用对 config
的引用,因为这个函数可以在 main 函数完成后调用,因此 config 结构不再存在。
我的想法是创建一个配置结构的副本(它只是几个原始变量),它与原始变量分开存在,因此我不会遇到生命周期或所有权问题。
这是正确的方法吗?我究竟做错了什么?我得到了与借用配置结构相同的错误:
error[E0373]: closure may outlive the current function, but it borrows `config`, which is owned by the current function
--> src/main.rs:36:34
|
36 | application.connect_activate(|app| {
| ^^^^^ may outlive borrowed value `config`
37 | build_ui(app, config.clone());
| ------ `config` is borrowed here
最佳答案
类似问题的最小再现:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
let print_cloned_s = || println!("{}", s.clone());
move_and_print(s);
print_cloned_s();
}
编译器提示:
error[E0505]: cannot move out of `s` because it is borrowed
我想克隆 s
以避免借用,从而允许以后使用它。那么,编译器怎么会说 s
是借来的呢?
前面的推理是完全正确的,但是,有一个微妙之处:Clone::clone
的签名是 clone(&self) -> Self
。所以当clone
被调用时,数据被clone函数借用!
解决方案是在创建闭包之前克隆数据,然后将其移动到闭包中:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
// I clone `s` BEFORE creating the closure:
let cloned_s = s.clone();
// Then I move the cloned data into the closure:
let print_cloned_s = move || println!("{}", cloned_s);
move_and_print(s);
print_cloned_s();
}
正如我所说,您必须克隆配置并将此克隆移动到闭包中:
let cloned_config = config.clone();
application.connect_activate(move |app| {
build_ui(app, cloned_config.clone());
});
您还必须添加第二个克隆调用以允许闭包是 Fn
而不是 FnOnce
。实际上,如果您将配置移动到 build_ui
中,该函数将无法使用两次。参见 this question获取更多信息。
如果我很好地理解您的需要,config
旨在成为必须共享的只读配置。在这种情况下,我根本不会移动它,例如将 build_ui
的签名更改为:
fn build_ui(application: >k::Application, config: &Config)
关于rust - 为什么在闭包内克隆数据不能防止错误 "closure may outlive the current function"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57659707/
我在一个 twig 模板中使用 Assetic 来指定要从我的包中使用的 2 个 JS 文件 { % javascripts '@JiraExtendedReportsBund
我正在做一个 VS 包,它在菜单中有一个 DynamicItemStart 按钮。我在 VS 启动时加载动态按钮的内容没有任何问题,但我试图在某些事件(例如打开项目)之后向其内容添加更多命令。我将新命
需求是从plsql调用java方法,我可以通过loadjava命令来实现它。我遵循的步骤是: 第 1 步:创建 Java Class/jar 文件并将其放置在 Unix 机器上 第2步:将Java C
我是一名优秀的程序员,十分优秀!