rust - <T : Trait> Box<T> and &Trait/Box<Trait>? 有什么区别

标签 rust traits trait-objects

在编写带有特征的代码时,您可以将特征放在特征边界中:

use std::fmt::Debug;

fn myfunction1<T: Debug>(v: Box<T>) {
    println!("{:?}", v);
}

fn myfunction2<T: Debug>(v: &T) {
    println!("{:?}", v);
}

fn main() {
    myfunction1(Box::new(5));
    myfunction2(&5);
}

或直接在 Box 或引用类型中:

use std::fmt::Debug;

fn myfunction3(v: Box<Debug>) {
    println!("{:?}", v);
}

fn myfunction4(v: &Debug) {
    println!("{:?}", v);
}

fn main() {
    myfunction3(Box::new(5));
    myfunction4(&5);
}

这些给出相同的输出。那有什么区别呢?

(这个问题的灵感来自 another question,其中这只是几个混合概念之一)

最佳答案

<T: Trait> Box<T>你正在使用特征绑定(bind)来告诉编译器你想要一个 Box使用某种类型的实例 T实现Trait , 您将指定 T当你使用它时。 Rust 编译器可能会为每个不同的 T 创建不同的、高效的代码。在你的代码中(单态化)。

Box<Trait>你告诉编译器你想要一个 Box带有一个特征对象,一个指向实现 Trait未知类型的指针,这意味着编译器将使用动态调度。

我提供了两个示例,使区别更加清晰:

<T: Trait> Box<T> ,即特征界限:

use std::fmt::Debug;

struct Wrapper<T> {
    contents: Option<Box<T>>,
}

impl<T: Debug> Wrapper<T> {
    fn new() -> Wrapper<T> {
        Wrapper { contents: None }
    }

    fn insert(&mut self, val: Box<T>) {
    }
}

fn main() {
    let mut w = Wrapper::new();

    // makes T for w be an integer type, e.g. Box<i64>
    w.insert(Box::new(5));

    // type error, &str is not an integer type
    // w.insert(Box::new("hello"));
}

Box<Trait> ,即特征对象:

use std::fmt::Debug;

struct Wrapper {
    contents: Option<Box<Debug>>,
}

impl Wrapper {
    fn new() -> Wrapper {
        Wrapper { contents: None }
    }

    fn insert(&mut self, val: Box<Debug>) {
    }
}

fn main() {
    let mut w = Wrapper::new();
    w.insert(Box::new(5));
    w.insert(Box::new("hello"));
}

有关特征边界和特征对象之间差异的更多详细信息,我推荐 the section on trait objects in the first edition of the Rust book .

关于rust - <T : Trait> Box<T> and &Trait/Box<Trait>? 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45151770/

相关文章:

rust - 惯用地访问可变和不可变向量的元素

types - 为什么编译器需要特征的实现才能调用默认的自由函数?

rust - 从闭包返回闭包作为函数的返回值

rust - 如何将生命周期应用于 VecDeque<Box<dyn Trait>>?

rust - 如何在 Rust 数组中添加多个字符串?

rust - 如何从 Rust 中的不同线程写入文件?

struct - 是否有用于构造包含对临时对象的引用的结构的单行语法?

Scala 蛋糕模式鼓励硬编码依赖关系?

rust - 在 Rust 中的线程之间发送特征对象

rust - 如何在不分别分配堆上的每个项目的情况下创建拥有的特征对象列表?