引用的生命周期比相同范围内的值短?
Reference has shorter lifetime than its value from same scope?
在我的代码中,值似乎比对它的引用的寿命更长,即使两者都是在同一范围内创建的。我想知道为什么,以及如何调整我的引用的生命周期。
示例 1 被编译器接受...
let mut rxs: Vec<Receiver<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
rxs.push(rx);
}
但示例 2 不是...
let sel = Select::new();
let mut handles: Vec<Handle<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
handles.push(sel.handle(&rx));
}
编译器告诉我引用 &rx
在 for
循环的最后一行被 借用 ,但是被 丢弃 在 for
循环的末尾,需要更长的生命周期,大概是因为引用被放置在生命周期更长的结构中。为什么引用的生命周期与值不同,如果值可以移动到第一个示例中的结构中,为什么不能像第二个示例中那样引用?
最后,我想知道为什么我没有在示例 3 中遇到同样的问题,即使引用被借用并传递到持续时间更长的结构中比借用范围...
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.iter().map(|x| sel.handle(&x)).collect();
在第一个示例中,您将 rx
移动到 rxs
vec 中。这很好,因为您也移动了 rx
的所有权,它不会被删除。
在第二个示例中,您传递了对 sel.handle()
的引用,这是表示它被借用的另一种方式。 rx
在每次循环迭代结束时被丢弃,但 handles
比整个循环都长。如果编译器没有阻止这种情况发生,那么 handles
将充满悬空指针。
But why would the reference have a different lifetime than the value
引用的生命周期总是比它引用的值短。必须是这种情况:引用必须存在并分配到内存,然后才能找到它的地址。删除一个值后,对它的任何引用都指向释放的内存,这些内存可能被用于其他用途。
and if the value can be moved into a structure as in the first example, why not a reference like in the second?
在第二个示例中,正在移动引用 。但原始值不是。该引用现在指向 rx
.
之前使用的空闲内存
在第三个示例中,您创建了拥有所有 Sender
和 Receiver
的向量。只要 txs
和 rxs
仍在范围内,这些值就不会被删除。
在示例 2 中,rx
与 handles
的生命周期不同。事实上,它在循环结束时被丢弃,像这样:
let sel = Select::new();
let mut handles: Vec<Handle<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
handles.push(sel.handle(&rx));
drop(tx);
drop(rx);
}
drop(txs);
drop(handles);
drop(sel);
Example 3 is not equivalent to example 2. 这相当于示例 2,但它失败了:
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.into_iter().map(|x| sel.handle(&x)).collect(); // <-- notice: into_iter()
iter()
函数 returns 引用的迭代器。这就是它起作用的原因:
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.iter().map(|x| sel.handle(x)).collect(); // <-- notice: no `&`
在我的代码中,值似乎比对它的引用的寿命更长,即使两者都是在同一范围内创建的。我想知道为什么,以及如何调整我的引用的生命周期。
示例 1 被编译器接受...
let mut rxs: Vec<Receiver<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
rxs.push(rx);
}
但示例 2 不是...
let sel = Select::new();
let mut handles: Vec<Handle<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
handles.push(sel.handle(&rx));
}
编译器告诉我引用 &rx
在 for
循环的最后一行被 借用 ,但是被 丢弃 在 for
循环的末尾,需要更长的生命周期,大概是因为引用被放置在生命周期更长的结构中。为什么引用的生命周期与值不同,如果值可以移动到第一个示例中的结构中,为什么不能像第二个示例中那样引用?
最后,我想知道为什么我没有在示例 3 中遇到同样的问题,即使引用被借用并传递到持续时间更长的结构中比借用范围...
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.iter().map(|x| sel.handle(&x)).collect();
在第一个示例中,您将 rx
移动到 rxs
vec 中。这很好,因为您也移动了 rx
的所有权,它不会被删除。
在第二个示例中,您传递了对 sel.handle()
的引用,这是表示它被借用的另一种方式。 rx
在每次循环迭代结束时被丢弃,但 handles
比整个循环都长。如果编译器没有阻止这种情况发生,那么 handles
将充满悬空指针。
But why would the reference have a different lifetime than the value
引用的生命周期总是比它引用的值短。必须是这种情况:引用必须存在并分配到内存,然后才能找到它的地址。删除一个值后,对它的任何引用都指向释放的内存,这些内存可能被用于其他用途。
and if the value can be moved into a structure as in the first example, why not a reference like in the second?
在第二个示例中,正在移动引用 。但原始值不是。该引用现在指向 rx
.
在第三个示例中,您创建了拥有所有 Sender
和 Receiver
的向量。只要 txs
和 rxs
仍在范围内,这些值就不会被删除。
在示例 2 中,rx
与 handles
的生命周期不同。事实上,它在循环结束时被丢弃,像这样:
let sel = Select::new();
let mut handles: Vec<Handle<String>> = Vec::new();
let mut txs: Vec<SyncSender<String>> = Vec::new();
for _ in 0..N {
let (tx, rx) = sync_channel(0);
txs.push(tx);
handles.push(sel.handle(&rx));
drop(tx);
drop(rx);
}
drop(txs);
drop(handles);
drop(sel);
Example 3 is not equivalent to example 2. 这相当于示例 2,但它失败了:
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.into_iter().map(|x| sel.handle(&x)).collect(); // <-- notice: into_iter()
iter()
函数 returns 引用的迭代器。这就是它起作用的原因:
let (txs, rxs): (Vec<SyncSender<String>>, Vec<Receiver<String>>) =
(0..N).map(|_| sync_channel(0)).unzip();
let handles: Vec<Handle<String>> =
rxs.iter().map(|x| sel.handle(x)).collect(); // <-- notice: no `&`