Я новичок в Rust. Я хотел бы иметь возможность создавать переменную со статическим временем жизни внутри функции и возвращать ссылку на нее. Как можно выполнить следующее в Rust:
std::vector<int>& get_ints() {
static bool run_yet = false;
static std::vector<int> ints;
if ( ! run_yet ) {
run_yet = true;
for ( int i=0; i < 10; ++i ) {
ints.push_back(i);
}
}
return ints;
}
Я считаю, что это может иметь какое-то отношение к жизням, но я не уверен.
Чтобы внести ясность, ints
в вашем примере кода не выделяется в куче. Ему принадлежит выделение кучи, но здесь вы не возвращаете ссылку на выделение кучи. Вы возвращаете ссылку на значение, которому принадлежит выделение. Тот факт, что выделение кучи вообще происходит, на самом деле является деталью реализации, поэтому ваш вопрос на самом деле не связан с распределением кучи в каком-либо значимом смысле. (Вы можете спросить то же самое, например, о массиве, который не будет выделяться в куче.)
OnceLock делает то, что вы ищете. Он запустит код в get_or_init
, только если он не запускался ранее.
use std::sync::OnceLock;
pub fn get_ints() -> &'static [u32] {
static CELL: OnceLock<Vec<u32>> = OnceLock::new();
CELL.get_or_init(|| (0..10).collect()).as_slice()
}
fn main() {
println!("{:?}", get_ints());
}
Возвращать Vec
довольно бессмысленно, хотя если это не mut
... &'static [u32]
было бы более «лучшей практикой».
абсолютно верно, отредактировано соответственно.
Лично я бы пошел дальше и сохранил его в куче в Box<[u32]>
. Также мелкие гниды: ::<Vec<u32>>
является излишним, поскольку это можно сделать вывод, и .as_slice()
является лишним, поскольку для него будет применено автоматическое разыменование. детская площадка
Да, кроме того, ОП исключил 10, так что правильный диапазон будет 0..10
.
Вы спрашиваете о статическом объекте OnceCell?