English 中文(简体)
Creating an alias for a variable
原标题:

I have the following code in Rust (which will not compile but illustrates what I am after). For readability purposes, I would like to refer the same string with two different names so that the name of variables passed to a function match their real meaning. This can be "solved" if I clone date_created but then I m needlessly copying data.

let date_created: String = utc_now_str();
let paste_state_date = date_created;

// ...

some_function( date_created, paste_state_date );

Is there an efficient idiomatic way to create this "second name" for the same variable?

问题回答

I thought I understood that, but the following does not work because constructing the reference to the original borrows the original and so it seems I can t use both during the invocation of a function. Am I missing something really simple?

let str1 = ...; 
let str2 = &str1;
my_func(str1, *str2);

Are you familiar with how assignment in Rust works differently than assignment in C++? Here s a simple example:

 let x = "hello".to_string();
 let y = x;

What do you expect the values of x and y to be after those statements execute in Rust? Answer: x has no value, y has the value "hello".to_string(). That s known in Rust as "a move"--in other words, assignment moves values from one variable to another.

In C++, if you write:

string x = "hello";
string y = x;

then C++ will copy "hello" into y, which will leave you with two strings in memory. You have to be aware of that difference when using assignment in Rust.

What can be confusing is that sometimes when you use assignment in Rust, the value will be copied. For instance:

let x = 10;
let y = x;

After those statements execute in Rust, both x and y have the value 10. In this case, Rust copies the value into y. For simple values, like integer, float, byte, and bool types, assignment copies the value into the new variable.

The reason the compiler won t let you write something like:

fn go(orig: String, orig_ref: &String) {
    println!("{orig}");
    println!("{orig_ref}");
}

fn main(){

    let pig = "pig".to_string();
    let pref = &pig;

    go(pig, pref);

}

is because calling the function involves an assignment:

 go(  pig     ,         pref);
       |                |
       V                V
fn go(orig: String, orig_ref: &String)  


    orig = pig      orig_ref = pref

Therefore, the String that was in pig is moved into orig, and pig becomes "uninitialized". That leaves pref pointing to pig, which is no longer valid. Rust was created to prevent C++ errors, like dangling pointers, so the compiler won t let you create a dangling pointer.

See the following for a more detailed description of how Python, C++, and Rust all take different approaches to the way assignment works:

how to reuse a struct instance with Rust

Because you seem to know C++, let s talk pointers. According to "Programming Rust (Revised 2nd edition)", a String type is a "fat" pointer: it consists of a length and a capacity, in addition to a pointer to some memory on the heap where the string is actually stored. For instance, if you write:

   let pig = "hi".to_string();

then this is the situation:

enter image description here

The length is the actual length of the string and the capacity is how many total characters can fit in the allocated memory before Rust needs to allocate more memory for the string. Like a regular pointer, a "fat" pointer is efficient to copy because it is only three "machine words" long--no matter how much memory is allocated on the heap.

Then if you write:

   let pref = &pig;

I think this is what happens: enter image description here
pref doesn t point to the memory on the heap where the string is stored, rather pref points to the 3-word String on the stack. Subsequently, if the String in pig is moved elsewhere, i.e. the 3-word fat pointer is copied to some other location on the stack and Rust "uninitializes" pig, then pref would become a dangling pointer.

Rust will automatically follow pointers to pointers to get to the actual string, and that is why when you write:

 println!("{}", pref);

Rust will output the string rather than an address.





相关问题
Creating an alias for a variable

I have the following code in Rust (which will not compile but illustrates what I am after). For readability purposes, I would like to refer the same string with two different names so that the name of ...

Rust Visual Studio Code code completion not working

I m trying to learn Rust and installed the Rust extension for VSCode. But I m not seeing auto-completions for any syntax. I d like to call .trim() on String but I get no completion for it. I read that ...

热门标签