我正在学习/试验Rust,在我用这种语言找到的所有优雅中,有一个让我感到困惑并且看起来完全不合适的特点.
在进行方法调用时,Rust会自动取消引用指针.我做了一些测试来确定确切的行为:
struct X { val: i32 }
impl std::ops::Deref for X {
type Target = i32;
fn deref(&self) -> &i32 { &self.val }
}
trait M { fn m(self); }
impl M for i32 { fn m(self) { println!("i32::m()"); } }
impl M for X { fn m(self) { println!("X::m()"); } }
impl M for &X { fn m(self) { println!("&X::m()"); } }
impl M for &&X { fn m(self) { println!("&&X::m()"); } }
impl M for &&&X { …Run Code Online (Sandbox Code Playgroud) devirtualize:由于某些保证更改是正确的,将虚拟/多态/间接函数调用更改为静态函数调用 - 来源:我自己
给定一个&dyn ToString使用静态已知类型创建的简单特征对象String:
fn main() {
let name: &dyn ToString = &String::from("Steve");
println!("{}", name.to_string());
}
Run Code Online (Sandbox Code Playgroud)
请问直接调用.to_string()使用<String as ToString>::to_string()吗?还是仅通过 trait 的 vtable 间接?如果是间接的,是否可以将这个调用去虚拟化?或者有什么基本的东西阻碍了这种优化?
这个问题的激励代码要复杂得多;它使用异步特征函数,我想知道Box<dyn Future>在某些情况下是否可以优化返回 a 。
使用包含返回引用的方法的特征对象的正确方法是Self什么?以下代码
trait Foo {
fn gen(&mut self) -> &Self;
fn eval(&self) -> f64;
}
struct A {
a : f64,
}
impl Foo for A {
fn gen(&mut self) -> &Self {
self.a = 1.2;
self
}
fn eval(&self) -> f64 {
self.a + 2.3
}
}
struct B;
impl Foo for B {
fn gen(&mut self) -> &Self {
self
}
fn eval(&self) -> f64 {
3.4
}
}
fn bar(f : &dyn Foo) {
println!("Result is …Run Code Online (Sandbox Code Playgroud) 如果我在下面的代码中创建c1类型Concrete1,是否有任何运行时开销?
pub trait ExampleTrait {
fn foo(&self);
}
pub struct Concrete1 {}
impl ExampleTrait for Concrete1 {
fn foo(&self) {}
}
pub struct Concrete2 {}
impl ExampleTrait for Concrete2 {
fn foo(&self) {}
}
fn main() {
let c1 = Concrete1 {};
c1.foo();
}
Run Code Online (Sandbox Code Playgroud)
这是否需要任何类型的 v 表查找或任何其他类型的开销?我想要一个特征,以便我可以在编译时强制执行Concrete1并Concrete2实现相同的方法集。
我将静态选择在主程序中使用哪种具体类型;这两个实现的存在只是为了在需要时我可以使用 trait 的替代实现。