Rust是否禁止自动取消引用Box类型?

2cmtqfgy  于 2023-04-30  发布在  其他
关注(0)|答案(2)|浏览(98)

Rust中对Box对象的方法调用会自动取消引用Box Package 器中包含的对象。
举个例子

let my_variable: std::boxed::Box<i32> = std::boxed::Box::new(42);

let my_new_variable = my_variable.ilog2();

这个例子是人为的。这里的重要概念是,函数(在本例中为ilog2)可以在 Package 在盒子中的某个类型(在本例中为i32)上调用。
在C++中,解引用和函数调用操作符是必需的:

// C++ would require this
my_new_variable = my_variable->ilog2();

我的问题如下:

  • “装箱”对象的自动解引用是否会阻止在Box类型本身上调用函数?这样的函数调用是否被隐式地 * 禁止 *?

进一步阐述:
类型Box包含一个名为leak的函数。

  • 如果方法调用隐式地取消引用Box的内容,那么如何在Box对象上调用函数leak()
  • 如果调用一个与Box对象相关的函数,在一个Box对象上,“只是工作”,那么如何消除两个同名函数调用之间的歧义?(一个与Box关联,一个与Box中包含的类型关联)

语法上:
如果Box Package 了类型T,使得我们有Box<T>Box有一个函数Box::leak()T有一个函数T::leak(),我们如何消除这两个函数调用之间的歧义?

6qftjkof

6qftjkof1#

这方面的细节可以在Method call expressions上的参考中找到。其要点如下
例如,如果接收器具有类型Box〈[i32;2]〉,则候选类型将是Box〈[i32;2]〉,&Box〈[i32;2]〉,&mut Box〈[i32;2]〉,[i32; 2](通过解引用),&[i32;2],&mut [i32;2],[i32](通过无大小强制),&[i32],最后&mut [i32]。
也就是说,如果Box<T>有一个方法.quack(),而T有一个同名的方法,则像foo.quack()这样的方法调用(其中foo的类型为Box<T>)将引用Box::quack()的实现;T::quack()被有效地遮蔽。至于你的问题,这并不会阻止Box类型(或任何其他Deref类型)实现其内部类型也实现的方法,反之亦然。
例如:

struct Foo<T>(T);

impl<T> std::ops::Deref for Foo<T> {
    type Target = T;
    
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> Foo<T> {
    fn quack(&self) {
        println!("foo!");
    }
}

struct Bar;

impl Bar {
    fn quack(&self) {
        println!("bar!")
    }
}

fn main() {
    let foobar = Foo(Bar);
    // This will print "foo!".
    // Removing/renaming `Foo:quack` prints "bar!" without any change here
    foobar.quack();
}

几乎在所有情况下,这种行为都为调用 Package 在智能指针中的任何T上的方法带来了方便。为了在视觉上/心理上消除对T和智能指针本身没有方法,但智能指针本身通常没有方法,只有关联的函数。Box::leak()是一个例子,还有许多其他例子,它们强制使用像Box::leak(foo);这样的语法,而不是foo.leak();来实现 visual 消除歧义。
一个存在视觉/心理歧义的例子是Rc/Arc上的Clone实现,其中调用foo.clone() * 看起来像 * 克隆内部T,而实际上,只是克隆(增加引用计数)外部Rc/Arc

q8l4jmvw

q8l4jmvw2#

除了使用方法语法之外,你还可以使用完全限定名,所以即使Foo::quack隐藏了Bar::quack,你仍然可以使用它,定义为this other answer

fn main() {
    let foobar = Foo(Bar);
    // This will print "foo!".
    // Removing/renaming `Foo:quack` prints "bar!" without any change here
    foobar.quack();
    Foo::quack(&foobar); // will print "foo!" no matter what
    Bar::quack(&foobar); // will print "bar!" no matter what

}

相关问题