How to initialize a variable with a lifetime?

I have the following code and don’t know how to make it work:

fn new_int<'a>() -> &'a isize { &5 } fn main() { let x = new_int(); } 

Or another attempt:

 fn new_int<'a>() -> &'a isize { let a: &'a isize = &5; a } fn main() { let x = new_int(); } 
+7
rust lifetime
source share
2 answers

You can not. The lifetime parameter does not allow you to choose how long the value lives; it only allows you to tell the compiler that two or more links are associated with the same memory and are expected to have the same life.

A function (e.g. new_int in your case) can allocate memory in two ways:

  • locally in the area (stack) that is allocated to the function itself and is destroyed upon return from the function
  • dynamically in a memory area that is common to all functions (often called a "heap", although this is not always correct in all cases)

A reference ( & ) is a pointer to a memory location. It can point to a local stack or to a heap. Since dynamic allocations are much more expensive in terms of performance than writing to the stack, Rust uses the default stack (you need to use a box to perform dynamic allocation).

So, in short, this is why your code is illegal:

 fn new_int<'a>() -> &'a isize { let a: &'a isize = &5; // write 5 on the local stack a // return a pointer to that area of memory } // the area of memory where I wrote 5 is destroyed here, // so the pointer I'm trying to return is not valid 

You can either return a value

 fn new_int() -> isize { 5 } fn main() { let a = new_int(); // the value 5 (not a pointer) is copied into a } 

or perform dynamic allocation (which is redundant in the case of isize, but may make sense if you are really working with a large structure)

 fn new_int() -> Box<isize> { Box::new(5) } fn main() { let a = *new_int(); } 

alternatively, you can allocate memory outside the function and change it in the function. Usually you do not do this for a primitive type, but it makes sense in some scenarios (e.g. streaming data):

 // new_int does not return anything. Instead it mutates // the old_int in place fn new_int(old_int: &mut isize) { *old_int = 5; } fn main() { let mut a = 2; // memory for an int is allocated locally // in main() new_int(&mut a); // a mutable reference to that memory is passed // to new_int, that overwrites it with another value } 

As @dk is mentioned in a comment below, in this particular case (i.e. your function always returns 5 or another statically known value, and not something computed dynamically by a function), you can also return a link with 'static lifetime:

 fn new_int<'a>() -> &'a isize { static FIVE: isize = 5; &FIVE } 

More on ' static in Rust Reference .

Starting with Rust 1.21, this "static action" is now executed automatically and your source code is compiled. It creates the equivalent of static FIVE .

+9
source share

An alternative way to understand why

 fn new_int<'a>() -> &'a isize { &5 } 

cannot work as follows. 'a is the parameter of the lifetime of the function; that is, the caller selects the actual value of this parameter, not the function itself. For example, the caller may select 'static lifetime:

 let i: &'static isize = new_int(); 

However, &5 cannot have a 'static lifetime, so the function is rejected.

In other words, such a declaration basically says: "I can give you a link to any of your life." Naturally, this is true only if the link returned by the function has a 'static lifetime, which is the largest possible for life. This is what DC. tells, by the way.

+5
source share

All Articles