将 PathBuf 转换为 String 时是否有避免克隆的方法?
Is there a way to avoid cloning when converting a PathBuf to a String?
我需要简单地(并且危险地 - 为简洁起见省略了错误处理)获取当前的可执行文件名称。我让它工作了,但是我的函数将 &str
转换为 String
只是为了稍后调用 as_str()
进行模式匹配。
fn binary_name() -> String {
std::env::current_exe().unwrap().file_name().unwrap().to_str().unwrap().to_string()
}
据我了解,std::env::current_exe()
授予我 PathBuf
的所有权,我可以通过 return 转让它。就目前而言,我借用它来将其转换为&str
。从那里,return 字符串的唯一方法是在删除 PathBuf
之前克隆它。
有什么办法可以避免这种&OsStr -> &str -> String -> &str
循环吗?
Is there a way to avoid cloning when converting a PathBuf
to a String
?
当然可以。但是,那不是你在做什么。您正在通过 file_name
获取 PathBuf
的 部分 并将其转换。您不能取得字符串的一部分的所有权。
如果您没有采用子集,则可以通过转换为 OsString
然后转换为 String
来完成整个 PathBuf
的转换。在这里,我忽略了具体的错误,只是 return 成功或失败:
use std::path::PathBuf;
fn exe_name() -> Option<String> {
std::env::current_exe()
.ok()
.map(PathBuf::into_os_string)
.and_then(|exe| exe.into_string().ok())
}
Is there any way to avoid this &OsStr -> &str -> String -> &str
cycle?
不,因为您正在您的方法中创建 String
(或 OsString
或 PathBuf
,取决于代码的变体,以拥有所有权者为准)。查看 为什么不能 return 引用 stack-allocated 项(包括字符串)。
如该问答中所述,如果您想要引用,则拥有数据的事物必须比引用更长久:
use std::env;
use std::path::Path;
use std::ffi::OsStr;
fn binary_name(path: &Path) -> Option<&str> {
path.file_name().and_then(OsStr::to_str)
}
fn main() {
let exe = env::current_exe().ok();
match exe.as_ref().and_then(|e| binary_name(e)) {
Some("cat") => println!("Called as cat"),
Some("dog") => println!("Called as dog"),
Some(other) => println!("Why did you call me {}?", other),
None => println!("Not able to figure out what I was called as"),
}
}
您的原始代码可以编写成不会轻易因错误而崩溃
fn binary_name() -> Option<String> {
let exe = std::env::current_exe();
exe.ok()
.as_ref()
.and_then(|p| p.file_name())
.and_then(|s| s.to_str())
.map(String::from)
}
我需要简单地(并且危险地 - 为简洁起见省略了错误处理)获取当前的可执行文件名称。我让它工作了,但是我的函数将 &str
转换为 String
只是为了稍后调用 as_str()
进行模式匹配。
fn binary_name() -> String {
std::env::current_exe().unwrap().file_name().unwrap().to_str().unwrap().to_string()
}
据我了解,std::env::current_exe()
授予我 PathBuf
的所有权,我可以通过 return 转让它。就目前而言,我借用它来将其转换为&str
。从那里,return 字符串的唯一方法是在删除 PathBuf
之前克隆它。
有什么办法可以避免这种&OsStr -> &str -> String -> &str
循环吗?
Is there a way to avoid cloning when converting a
PathBuf
to aString
?
当然可以。但是,那不是你在做什么。您正在通过 file_name
获取 PathBuf
的 部分 并将其转换。您不能取得字符串的一部分的所有权。
如果您没有采用子集,则可以通过转换为 OsString
然后转换为 String
来完成整个 PathBuf
的转换。在这里,我忽略了具体的错误,只是 return 成功或失败:
use std::path::PathBuf;
fn exe_name() -> Option<String> {
std::env::current_exe()
.ok()
.map(PathBuf::into_os_string)
.and_then(|exe| exe.into_string().ok())
}
Is there any way to avoid this
&OsStr -> &str -> String -> &str
cycle?
不,因为您正在您的方法中创建 String
(或 OsString
或 PathBuf
,取决于代码的变体,以拥有所有权者为准)。查看
如该问答中所述,如果您想要引用,则拥有数据的事物必须比引用更长久:
use std::env;
use std::path::Path;
use std::ffi::OsStr;
fn binary_name(path: &Path) -> Option<&str> {
path.file_name().and_then(OsStr::to_str)
}
fn main() {
let exe = env::current_exe().ok();
match exe.as_ref().and_then(|e| binary_name(e)) {
Some("cat") => println!("Called as cat"),
Some("dog") => println!("Called as dog"),
Some(other) => println!("Why did you call me {}?", other),
None => println!("Not able to figure out what I was called as"),
}
}
您的原始代码可以编写成不会轻易因错误而崩溃
fn binary_name() -> Option<String> {
let exe = std::env::current_exe();
exe.ok()
.as_ref()
.and_then(|p| p.file_name())
.and_then(|s| s.to_str())
.map(String::from)
}