2016-06-13 48 views
2

考虑以下两个结构:是否有可能通过引用返回结构的一部分?

pub struct BitVector<S: BitStorage> { 
    data: Vec<S>, 
    capacity: usize, 
    storage_size: usize 
} 

pub struct BitSlice<'a, S: BitStorage> { 
    data: &'a [S], 
    storage_size: usize 
} 

哪里BitStorage实际上是被限制在所有无符号整数(U8,U16,U32,U64,USIZE)类型。

如何实施Deref特质? (BitVector<S> derefs到BitSlice<S>类似于如何Vec<S> derefs至&[S]

我曾尝试以下(请注意,它不会由于与寿命问题的编译,但更重要的是,因为我尝试在堆栈上返回值参考):

impl<'b, S: BitStorage> Deref for BitVector<S> { 
    type Target = BitSlice<'b, S>; 

    fn deref<'a>(&'a self) -> &'a BitSlice<'b, S> { 
     let slice = BitSlice { 
      data: self.data, 
      storage_size: self.storage_size, 
     }; 
     &slice 
    } 
} 

我知道可以通过引用返回一个结构的领域,因此,例如,我可以在Deref性状返回&Vec<S>&usize,但有可能返回一个BitSlice注意到我基本上拥有中的所有数据210已经作为Vec<S>可以转换成&[S]storage_size已经在那里?

我会认为这是可能的,如果我可以使用这两个值创建一个结构,并以某种方式告诉编译器忽略这一事实,即它是在堆栈上创建的结构,而不是使用现有的值,但我有不知道如何。

回答

2

Deref需要返回参考。一个参考总是指向一些现有的内存,并且任何局部变量都不会存在足够长的时间。从理论上讲,您可以在deref中创建一个新对象,并返回对它的引用,但我知道的所有内容都会导致内存泄漏。让我们忽略这些技术问题,只是说这根本不可能。

现在呢?你将不得不改变你的API。 Vec可以实现Deref,因为它破坏到[T],而不是&[T]或类似的东西。您可能使用相同的策略获得成功:使BitSlice<S>为仅包含切片[S]的未分类类型,以便返回类型为&'a BitSlice<S>。这假定storage_size成员是不需要的。但看起来这是指逻辑有效的位数(即,可以在不扩展位向量的情况下访问),如果是这样的话,那似乎是不可避免的。

另一种替代方法当然是不执行Deref。不方便,但如果您的切片数据类型距实际切片太远,则可能是唯一的选择。

RFC PR #1524建议自定义动态大小的类型,那么你可以有一个BitSlice<S>类型,就像一个切片,但可以有其他内容,如storage_size。然而,这还不存在,如果它永远不会确定的话。

然而BitVector上的capacity成员似乎毫无意义。这不仅仅是sizeof S * 8

+0

你的想法是正确的,即'storage_size'不是必需的,它只是'std :: mem :: size_of :: ()* 8',但是恐怕需要'capacity',因为你可以分配位向量不是后备存储的乘积,即。后备存储是u32,你想分配50位,但是如果这样做可以解除压缩的作用,强制分配多个后备存储器可能是合理的 – skiwi

相关问题