- 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/
我正在尝试对 StockData 表执行 OHCL sql 查询 (SQL Server 2012)。每天有数千行添加到表中,我想获取每天的开盘价、最高价、最低价和收盘价数据。 建表sql如下:
我是一名优秀的程序员,十分优秀!