Rust 'borrowed value does not live long enough' 在分配给静态变量时
Rust 'borrowed value does not live long enough' while assigning to a static variable
我的目标是保留一个静态变量并让该值被 CLI 参数覆盖,但我很难找到一种方法来保留我从 args 迭代器获得的值的静态副本。
static mut ROOT_DIRECTORY: &str = "C:\test\source";
fn main() {
let args: Vec<String> = env::args().collect();
let mut index = 0;
for arg in args {
match arg.as_str() {
"/r" => unsafe {
if args_length <= index + 1 {
panic!("Missing root directory value.");
}
ROOT_DIRECTORY = args.get(index + 1).unwrap();
if ROOT_DIRECTORY.is_empty() {
panic!("Root directory value cannot be empty.")
}
}
}
}
}
给出如下编译错误
error[E0597]: `args` does not live long enough
--> src\main.rs:90:34
|
90 | ROOT_DIRECTORY = args.get(index + 1).unwrap();
| ^^^^---------------
| |
| borrowed value does not live long enough
| argument requires that `args` is borrowed for `'static`
...
168 | }
| - `args` dropped here while still borrowed
error[E0382]: borrow of moved value: `args`
--> src\main.rs:90:34
|
54 | let args: Vec<String> = env::args().collect();
| ---- move occurs because `args` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
...
76 | for arg in args {
| ----
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&args`
...
90 | ROOT_DIRECTORY = args.get(index + 1).unwrap();
|
我有什么方法可以从迭代器创建值的静态副本吗?
你不能那样做。静态变量必须是 'static
,即不能包含非 'static
的生命周期。这就是为什么您可以在静态引用的声明中省略生命周期。你的实际上相当于:
static mut ROOT_DIRECTORY: &'static str = "C:\test\source";
而您的 args
是局部变量,因此对它的引用不是 'static
。
Is there any way for me to create a static copy of the value from the iterator?
最简单的选择是让静态变量拥有它的数据,而不是引用,也就是说,让它成为一个String
。不幸的是,静态构造函数必须是 const
,而我所知道的 String
的唯一 const
构造函数是 String::new()
。您可以添加一个辅助函数 fn get_root_directory() -> &'static str
来读取全局变量和 returns 默认值(如果未设置),但如果您喜欢它,您可以将静态设置为 Option<String>
:
static mut ROOT_DIRECTORY: Option<String> = None;
pub fn get_root_directory() -> &'static str {
unsafe {
ROOT_DIRECTORY.as_deref().unwrap_or("C:\test\source")
}
}
另一种选择是泄漏堆分配的字符串以使其成为静态的。只要你只分配给它一次,泄漏应该不是问题。类似于:
static mut ROOT_DIRECTORY: &'static str = "default value";
fn main() {
let x = "...".to_string();
unsafe {
ROOT_DIRECTORY = Box::leak(x.into_boxed_str());
}
}
我的目标是保留一个静态变量并让该值被 CLI 参数覆盖,但我很难找到一种方法来保留我从 args 迭代器获得的值的静态副本。
static mut ROOT_DIRECTORY: &str = "C:\test\source";
fn main() {
let args: Vec<String> = env::args().collect();
let mut index = 0;
for arg in args {
match arg.as_str() {
"/r" => unsafe {
if args_length <= index + 1 {
panic!("Missing root directory value.");
}
ROOT_DIRECTORY = args.get(index + 1).unwrap();
if ROOT_DIRECTORY.is_empty() {
panic!("Root directory value cannot be empty.")
}
}
}
}
}
给出如下编译错误
error[E0597]: `args` does not live long enough
--> src\main.rs:90:34
|
90 | ROOT_DIRECTORY = args.get(index + 1).unwrap();
| ^^^^---------------
| |
| borrowed value does not live long enough
| argument requires that `args` is borrowed for `'static`
...
168 | }
| - `args` dropped here while still borrowed
error[E0382]: borrow of moved value: `args`
--> src\main.rs:90:34
|
54 | let args: Vec<String> = env::args().collect();
| ---- move occurs because `args` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
...
76 | for arg in args {
| ----
| |
| value moved here
| help: consider borrowing to avoid moving into the for loop: `&args`
...
90 | ROOT_DIRECTORY = args.get(index + 1).unwrap();
|
我有什么方法可以从迭代器创建值的静态副本吗?
你不能那样做。静态变量必须是 'static
,即不能包含非 'static
的生命周期。这就是为什么您可以在静态引用的声明中省略生命周期。你的实际上相当于:
static mut ROOT_DIRECTORY: &'static str = "C:\test\source";
而您的 args
是局部变量,因此对它的引用不是 'static
。
Is there any way for me to create a static copy of the value from the iterator?
最简单的选择是让静态变量拥有它的数据,而不是引用,也就是说,让它成为一个String
。不幸的是,静态构造函数必须是 const
,而我所知道的 String
的唯一 const
构造函数是 String::new()
。您可以添加一个辅助函数 fn get_root_directory() -> &'static str
来读取全局变量和 returns 默认值(如果未设置),但如果您喜欢它,您可以将静态设置为 Option<String>
:
static mut ROOT_DIRECTORY: Option<String> = None;
pub fn get_root_directory() -> &'static str {
unsafe {
ROOT_DIRECTORY.as_deref().unwrap_or("C:\test\source")
}
}
另一种选择是泄漏堆分配的字符串以使其成为静态的。只要你只分配给它一次,泄漏应该不是问题。类似于:
static mut ROOT_DIRECTORY: &'static str = "default value";
fn main() {
let x = "...".to_string();
unsafe {
ROOT_DIRECTORY = Box::leak(x.into_boxed_str());
}
}