2015-04-27 1 views
2

Я совершенно запутался о жизни после этой ошибки:Невозможно вставить ссылку в HashMap, если он объявлен после того, как данные я вставив

#![feature(collections)] 
use std::collections::BitVec; 
use std::collections::HashSet; 

fn main() { 
    let mut hs = HashSet::new(); 

    let zeros : BitVec = BitVec::from_elem(10,false); 
    let ones : BitVec = BitVec::from_elem(10,true);  
    println!("{:?}\n{:?}",zeros,ones); 
    // let mut hs = HashSet::new(); // works only if move this line to #7 

    hs.insert(&zeros); 
    hs.insert(&ones); 
    println!("{:?}",hs); 
} 

Это дает мне ошибку:

<anon>:14:16: 14:21 error: `zeros` does not live long enough 
<anon>:14  hs.insert(&zeros); 
         ^~~~~ 
<anon>:7:33: 17:2 note: reference must be valid for the block suffix following statement 0 at 7:32... 
<anon>:7  let mut hs = HashSet::new(); 

Но если я объявить hs позже, сразу после zeros и ones, все работает отлично:

#![feature(collections)] 
use std::collections::BitVec; 
use std::collections::HashSet; 

fn main() { 
    // let mut hs = HashSet::new(); 

    let zeros : BitVec = BitVec::from_elem(10,false); 
    let ones : BitVec = BitVec::from_elem(10,true);  
    println!("{:?}\n{:?}",zeros,ones); 
    let mut hs = HashSet::new(); // works only if move this line to #7 

    hs.insert(&zeros); 
    hs.insert(&ones); 
    println!("{:?}",hs); 
} 

Выход:

0000000000 
1111111111 
{0000000000, 1111111111} 
Program ended. 

Вы можете попробовать код here.

-

Я задал этот вопрос на IRC получил следующий ответ:

talchas: basically objects are destroyed line by line (well, statement by statement) in reverse order they were created,so if the bitsets were destroyed before the hashset, then the hashset's destructor would run with invalid pointers in it. if you declare them afterwards they get destroyed before the hashset does and you have references to them in the hashset.

so for this in particular, there's https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md and probably some discussion in pull requests and such

reem: The RFC that introduced it goes into great detail https://github.com/rust-lang/rfcs/blob/f78aa94fd44c890ef5091a646db4d4159d21e1e2/text/0000-sound-generic-drop.md , but might not be the best thing to read to just get a quick understand.

ответ

3

Тип hs является HashSet<&'ρ BitVec> бут что ?

сообщение об ошибке объясняет это немного:

<anon>:7:33: 17:2 note: reference must be valid for the block suffix following statement 0 at 7:32... 
<anon>:7  let mut hs = HashSet::new(); 

Это говорит о том, что ссылка должна быть законна для остальной части блока после строки 7, где HashSet определен.

Это, то, что является: остальная часть блока после строки 7.

Подумайте об этом так: когда HashSet<&BitVec> создается, будет ли это законно немедленно вставить значения? Нет, потому что они являются ссылками на вещи, которые еще не существуют.

Если вы вставив BitVec сек, а не ссылки на них, проблема уйдет, ибо в то время как срок службы &'ρ BitVec является , время жизни BitVec является 'static, так как она не содержит не-статические данные и т.д. вставка hs.insert(BitVec::from_elem(10, false)) будет в порядке.

Теперь почему компилятор не разрешил более раннее определение hs? Когда он вводит тип, он должен быть типом, который является законным там, где он есть. Если бы было указано на срок жизни «после строки 13», когда декларация hs находится в строке 7, у вас будет что-то, что не является законным во время его объявления. В этом конкретном случае ничего не делается с THashSet<T> в вызове new, поэтому вы можете сказать, что теоретически компилятор может игнорировать тот факт, что он имеет дело с незаконным типом, который станет законным к моменту нашего фактического использования, но это было бы совершенно злым и непоследовательным (изменения в теле функции могут потенциально повлиять на звонящих), поэтому Rust запрещает весь класс поведения.

+0

спасибо за ваше проницательное объяснение, снова! –

Смежные вопросы