从 rust 的引用中获取 Box Pointer
Get Box Pointer from reference in rust
假设我有这样的函数:
fn foo(item: &FooType) -> Box<FooType>{
Box::new(item)
}
我收到以下错误:
mismatched types: expected enum FooType
, found &FooType
我假设我需要做一些 reference/boxing 和一生的魔法,但作为一个 Rust 初学者,我不是 100% 确定如何让它工作。
编译器报错是因为在函数的签名中您将 Box<FooType>
指定为 return 类型,并且在包装 ìtem
时给它一个 Box<&FooType>
在 Box
.
更改函数的签名,使其接收 FooType
而不是像这样对它的引用:
fn foo(item: FooType) -> Box<FooType>{
Box::new(item)
}
我认为没有明确的答案,因为这取决于您的期望。
如果您想获得您想要保持可用的东西的堆分配克隆,那么在 foo1()
中进行克隆会有所帮助。
更好的解决方案可能是传递 值 而不是引用,如 foo2()
中那样,因为这样调用站点可以决定是否需要克隆或如果将原始值移动到框中就足够了。
您可能还希望该框包含引用而不是值,如 foo3()
中那样,但这对我来说就像代码的味道(许多间接使关于生命周期的推理变得非常复杂)。
#[derive(Debug, Clone)]
struct FooType {
value: usize,
}
fn foo1(item: &FooType) -> Box<FooType> {
Box::new(item.clone())
}
fn foo2(item: FooType) -> Box<FooType> {
Box::new(item)
}
fn foo3(item: &FooType) -> Box<&FooType> {
Box::new(item)
}
fn main() {
let ft_a = FooType { value: 12 };
let bft_a = foo1(&ft_a);
println!("bft_a: {:?}", bft_a);
println!("ft_a: {:?}", ft_a);
println!("~~~~~~~~~~~~~~~~~~");
let ft_b = FooType { value: 34 };
let bft_b = foo2(ft_b);
println!("bft_b: {:?}", bft_b);
// println!("ft_b: {:?}", ft_b); // borrow of moved value: `ft_b`
println!("ft_b is consumed");
println!("~~~~~~~~~~~~~~~~~~");
let ft_c = FooType { value: 56 };
let bft_c = foo2(ft_c.clone());
println!("bft_c: {:?}", bft_c);
println!("ft_c: {:?}", ft_c);
println!("~~~~~~~~~~~~~~~~~~");
let ft_d = FooType { value: 78 };
let bft_d = foo3(&ft_d);
println!("bft_d: {:?}", bft_d);
println!("ft_d: {:?}", ft_d);
}
/*
bft_a: FooType { value: 12 }
ft_a: FooType { value: 12 }
~~~~~~~~~~~~~~~~~~
bft_b: FooType { value: 34 }
ft_b is consumed
~~~~~~~~~~~~~~~~~~
bft_c: FooType { value: 56 }
ft_c: FooType { value: 56 }
~~~~~~~~~~~~~~~~~~
bft_d: FooType { value: 78 }
ft_d: FooType { value: 78 }
*/
假设我有这样的函数:
fn foo(item: &FooType) -> Box<FooType>{
Box::new(item)
}
我收到以下错误:
mismatched types: expected enum
FooType
, found&FooType
我假设我需要做一些 reference/boxing 和一生的魔法,但作为一个 Rust 初学者,我不是 100% 确定如何让它工作。
编译器报错是因为在函数的签名中您将 Box<FooType>
指定为 return 类型,并且在包装 ìtem
时给它一个 Box<&FooType>
在 Box
.
更改函数的签名,使其接收 FooType
而不是像这样对它的引用:
fn foo(item: FooType) -> Box<FooType>{
Box::new(item)
}
我认为没有明确的答案,因为这取决于您的期望。
如果您想获得您想要保持可用的东西的堆分配克隆,那么在 foo1()
中进行克隆会有所帮助。
更好的解决方案可能是传递 值 而不是引用,如 foo2()
中那样,因为这样调用站点可以决定是否需要克隆或如果将原始值移动到框中就足够了。
您可能还希望该框包含引用而不是值,如 foo3()
中那样,但这对我来说就像代码的味道(许多间接使关于生命周期的推理变得非常复杂)。
#[derive(Debug, Clone)]
struct FooType {
value: usize,
}
fn foo1(item: &FooType) -> Box<FooType> {
Box::new(item.clone())
}
fn foo2(item: FooType) -> Box<FooType> {
Box::new(item)
}
fn foo3(item: &FooType) -> Box<&FooType> {
Box::new(item)
}
fn main() {
let ft_a = FooType { value: 12 };
let bft_a = foo1(&ft_a);
println!("bft_a: {:?}", bft_a);
println!("ft_a: {:?}", ft_a);
println!("~~~~~~~~~~~~~~~~~~");
let ft_b = FooType { value: 34 };
let bft_b = foo2(ft_b);
println!("bft_b: {:?}", bft_b);
// println!("ft_b: {:?}", ft_b); // borrow of moved value: `ft_b`
println!("ft_b is consumed");
println!("~~~~~~~~~~~~~~~~~~");
let ft_c = FooType { value: 56 };
let bft_c = foo2(ft_c.clone());
println!("bft_c: {:?}", bft_c);
println!("ft_c: {:?}", ft_c);
println!("~~~~~~~~~~~~~~~~~~");
let ft_d = FooType { value: 78 };
let bft_d = foo3(&ft_d);
println!("bft_d: {:?}", bft_d);
println!("ft_d: {:?}", ft_d);
}
/*
bft_a: FooType { value: 12 }
ft_a: FooType { value: 12 }
~~~~~~~~~~~~~~~~~~
bft_b: FooType { value: 34 }
ft_b is consumed
~~~~~~~~~~~~~~~~~~
bft_c: FooType { value: 56 }
ft_c: FooType { value: 56 }
~~~~~~~~~~~~~~~~~~
bft_d: FooType { value: 78 }
ft_d: FooType { value: 78 }
*/