변경 불가능한 상대와의 코드 중복을 피하기 위해 변경 가능한 반복기를 구현하기 위해 transmute를 사용하는 것이 안전합니까? [복제]

Nov 15 2020

Vec연속적이지 않은 방식으로 참조에서 데이터를 읽는 사용자 지정 반복기가 있습니다. 동일한 메모리에 대한 두 개의 참조를 반환하지 않으므로 가변 대응을 구현하는 것이 안전하다고 생각합니다.

그러나 반복자 자체의 논리는 매우 복잡하며 변경 가능한 버전의 경우 완전히 동일합니다. 코드 중복을 방지하기 위해 내부에서 뮤트가 아닌 이터레이터를 사용하고 그 결과를 캐스팅하여 가변성을 추가했습니다. 이것은 예상대로 작동하지만 어떤 종류의 정의되지 않은 동작을 호출하는지 확실하지 않습니다.

pub mod lib {
    pub struct Data {
        pub v: Vec<u64>,
    }

    impl Data {
        pub fn iter(&self) -> MyIter {
            MyIter {
                data: &self.v,
                i: 0,
            }
        }

        pub fn iter_mut(&mut self) -> MyIterMut {
            MyIterMut { iter: self.iter() }
        }
    }

    pub struct MyIter<'a> {
        data: &'a [u64],
        i: usize,
    }

    impl<'a> Iterator for MyIter<'a> {
        type Item = &'a u64;

        fn next(&mut self) -> Option<Self::Item> {
            if self.i == self.data.len() {
                return None;
            }
            let res = &self.data[self.i];
            self.i += 1;
            Some(res)
        }
    }

    pub struct MyIterMut<'a> {
        iter: MyIter<'a>,
    }

    impl<'a> Iterator for MyIterMut<'a> {
        type Item = &'a mut u64;

        fn next(&mut self) -> Option<Self::Item> {
            unsafe { std::mem::transmute(self.iter.next()) }
        }
    }
}

fn main() {
    let mut d = lib::Data { v: vec![0; 8] };

    for elem in d.iter_mut() {
        *elem = 123;
    }

    println!("{:?}", d.v);
}

완전한 작업 예

변경 가능한 반복기는 iter_mut메서드 에서만 생성됩니다 . 이것은 초기 값이 항상 변경 가능한 변수로 시작된다는 것을 의미합니다 &mut self. 변경 불가능한 변수에서이 변경 가능한 반복자를 구성하는 것은 불가능합니다.

C ++에서는 종종 const_castconstness 만 다른 구현을 복제하지 않기 위해 a 를 사용합니다 .

이것이 내가 Rust에서 할 수있는 일입니까?

답변

1 Aplet123 Nov 15 2020 at 09:30

MyIter원본 vec에 대한 변경 불가능한 참조가 포함 된 경우 ,의 여러 인스턴스를 가질 수 있으므로 변환 할 수 없어 MyIter참조 충돌이 발생합니다. 처럼 보인다 duplicate상자는 약간의 차이로 코드를 복제 할 수있는 쉬운 방법을 제공, 여기에 사용 될 수 있습니다.