首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 ><T: Trait> Box<T>和&Trait / Box<Trait>之间的区别是什么?

<T: Trait> Box<T>和&Trait / Box<Trait>之间的区别是什么?
EN

Stack Overflow用户
提问于 2017-07-17 19:02:39
回答 2查看 1.3K关注 0票数 13

在编写带有特征的代码时,您可以将该特性放在一个特征绑定中:

代码语言:javascript
复制
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或引用类型中:

代码语言:javascript
复制
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);
}

它们给出了同样的输出。那有什么区别呢?

(这个问题是由另一个问题提出的,这只是几个混合概念中的一个)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-17 19:02:39

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

使用Box<Trait>时,您正在告诉编译器,您需要一个带有属性对象的Box,一个指向实现Trait的未知类型的指针,这意味着编译器将使用动态调度。

我列举了两个例子,让区别变得更清楚了:

<T: Trait> Box<T>,即性状绑定:

代码语言:javascript
复制
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>,即特征对象:

代码语言:javascript
复制
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"));
}

关于特征边界和特征对象之间的差异的更多细节,我建议使用“锈书”第一版中关于特征对象的章节

票数 11
EN

Stack Overflow用户

发布于 2017-10-30 12:36:27

重要的是,没有将泛型类型放在引用后面(比如&Box),您可以直接接受它:

代码语言:javascript
复制
fn myfunction3<T: Debug>(v: T) {
    println!("{:?}", v);
}

fn main() {
    myfunction3(5);
}

这具有相同的单一组织化的好处,而不存在额外内存分配(Box)或需要在某个地方保留值的所有权(&)的缺点。

我想说的是,泛型通常应该是默认的选择--只有在动态调度/异质性存在时,才需要特性对象。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45151770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档