There are three pointer types: reference, Box, and primitive

Rust is designed to keep memory footprint to a minimum, so values in Rust are nested by default; for example, ((0,0), (1440, 900)) will be stored as four contiguously integers.

Reference types

  • References can be thought of as Rust’s basic pointer type.
  • A reference can point to any value on the stack or heap.
  • The expression &x produces a reference to x. (Borrowing a reference to X)
  • &x is an unmodifiable reference and &mut x is a modifiable reference.

Sample:

  • &String is read as “reference String” or String reference.
  • If you get a reference r, then *r is the value that r points to.

Box type

The easiest way to assign a value on the heap is to use Box::new, for example:

let t: (&str, i32) = ("aa", 10); let b = Box::new(t); / / b type is Box < (& STR, i32) > let c = Box: : the new (" the_str "); // c <&str> let d = Box::new(10); // the type of d is Box<i32>Copy the code

The original pointer

  • The primitive pointer types *const T and *mut T.
  • Dereference of an original pointer is normally only possible in an unsafe block.

Arrays, vectors, and slices

Rust has three types that represent a set of values in memory: arrays, vectors (Vec<T>), and slices (&[T], &mut[T])

An array of

  • The type [T;N] represents an array of N values, each of type T.

  • The size of the array is a constant determined at compile time, so the type must be Sized, or if it is a compound type, each property of the type must be Sized.

  • Three elements of an array: the element type is the same, the element size is clear, and the array length (the number of elements) is immutable.

  • Common initialization methods :(1) direct assignment; (1) Assign the initial value, then fill.

let arr_01: [i32; 6] = [1, 3, 5, 7, 9, 11]; let arr_02: [&str; 3] = ["aa", "bb", "cc"]; let mut arr_03 = ["aa".to_string(), "bb".to_string(), "cc".to_string()]; arr_03[0].push_str("bb"); println! ("arr_03 = {:? }", arr_03); // arr_03 = ["aabb", "bb", "cc"] let arr_04 = [0, 100]; // Initializes an array of 100 elements with an initial value of 0.Copy the code
  • You can call any method of a slice on an array (when a slice method is called, Rust implicitly converts a reference to an array to a reference to a slice)

vector

  • The type Vec

    , called a vector of type T, is a dynamically allocated, extensible sequence of values of type T.
  • The elements of a vector are kept on the heap, so it can be scaled at will (push in new elements, append other vectors, delete elements, and so on).

The way vectors are created

  1. The vec! Macro.
let mut v = vec! Hc-positie [2]; assert_eq! (v.iter().fold(1, |a, b| a * b), 210);Copy the code
  1. Create the vector using vector::new, and then push the elements in.
let mut v = Vec::new(); v.push("do"); v.push("not"); v.push("do"); v.push("that"); assert_eq! (vec! ["do", "not", "do", "that"], v);Copy the code
  1. Construct vectors based on the values generated by the iterator.
let v:Vec<i32> = (0.. 5).collect(); // collect println! ("v = {:? }", v); // v = [0, 1, 2, 3, 4] let v: Vec<i32> = (0.. =5).collect(); println! ("v = {:? }", v); // v = [0, 1, 2, 3, 4, 5]Copy the code
  1. It is recommended to use the Vec::with_capacity method to specify the capacity during initialization.

(Reduce capacity expansion overhead and allocate appropriate space at once.)

let mut v = Vec::<i32>::with_capacity(2); // let mut v: Vec<i32> = Vec::with_capacity(10); println! ("v.len() = {}, v.capacity() = {}", v.len(), v.capacity()); // v.len() = 0, v.capacity() = 2 v.push(1); v.push(2); v.push(3); println! ("v.len() = {}, v.capacity() = {}", v.len(), v.capacity()); // v.len() = 3, v.capacity() = 4Copy the code

Slice (slice quote)

  • Slice slice is written as [T] of unspecified length and represents a range of arrays or vectors.
  • Slices can only be passed by reference.
  • A reference to a slice is a fat pointer, double-word wide, that holds a pointer to the first element of the slice and the number of elements in the slice.
  • Example of traversal section:
fn print_slice(s: &[f64]) { for item in s { print! ("{} ", item); } } let vec: Vec<f64> = vec! [0.1, 0.732, 3.9, 0.301]. Let arr: [f64; 4] = [0.3, 12.56, 1.7, 3.1415926]. let vec_slice = &vec; &vec [64] let arr_slice = &arr; // &[f64;4] print_slice(vec_slice); // 0.1 0.732-3.9 0.301 println! (" "); print_slice(arr_slice); // 0.3-12.56 1.7 3.1415926 println! (" ");Copy the code
  • Use a range in an index to get a reference to an array or vector slice
Print_slice (&vec[0..=1]); / / 0.1 0.732 println! (a); print_slice(&arr[0..=1]); / / println 0.3 12.56! (a); let new_slice: &[f64] = &vec_slice[0..=1]; print_slice(new_slice); / / 0.1 0.732 println! (a);Copy the code

String type

String literals (&str)

  • String literals are enclosed in a pair of double quotes. (Therefore, double quotes need to be escaped).
  • If the string has a newline, that is, a multi-line string, the newline information is also preserved.
  • If a line in a multi-line string ends with a backslash \, the newline character for that line and the whitespace at the beginning of the next line are removed.
  • Raw string syntax: Prefixes the string with the R notation. If the original string contains double quotes (escaping is not possible), you need to prefix the string with r### and then ### #.
let aa = "This is &str"; println! ("{}", aa); // This is &str let aa = "This is &str"; // This is // &str println! ("{}", aa); let aa = "This is \ &str"; println! ("{}", aa); // This is &str let aa = r"This is \t str"; println! ("{}", aa); // This is \t str let aa = r###"This is \t str and "haha"."###; println! ("{}", aa); // This is \t str and "haha".Copy the code

Byte string

  • A byte string is a literal string with the prefix B.
  • Byte strings are slices of U8 values (that is, bytes), not slices of Unicode text.
  • Byte strings cannot contain any Unicode characters, only ASCII and \xHH escape sequences. // Because of the u8 limitation.
let method = b"GET"; // The type is &[u8;3], and a reference to a three-byte array assert_eq! (method, &[b'G', b'E', b'T']);Copy the code

An in-memory representation of a String

  • A Rust string is a sequence of Unicode characters, but it is not stored in memory as a CHAR array.
  • Strings are stored in memory using UTF-8 variable-width encoding. Each ASCII character in a string is stored in 1 byte, while other strings occupy more than one byte.
  • Strings are stored in a scalable cache (on the heap), so they can be resized on request or request. In fact, it is a Vec< U8 > that can store well-formed UTF-8.
  • & STR (string slice) is a reference to a string of UTF-8 text owned by another variable. & STR is also a fat pointer that contains the address of the actual data and its length. & STR is similar to &[T].
  • The.len() method of String or &str returns their length in bytes, not the number of characters.
  • &str is immutable, &mut STR (a variant of &mut String, requiring a variable of type &mut String) currently has only two methods to change its contents: Make_ascii_lowercase and make_ascii_uppercase.
let mut s = String::from("AdBcE"); test_mutstr(&mut s); // -------------------------- fn test_mutstr(ins: &mut str) { // ins.push_str("KdjAp"); // this is error ins.make_ascii_lowercase(); // adbce println! ("{}",ins); ins.make_ascii_uppercase(); // ADBCE println! ("{}",ins); }Copy the code

How a string is created

Like Vec, each String has a buffer allocated independently on the heap that can be transferred ownership or released (variables out of scope).

  • The.to_string() method converts & STR to String. It’s actually copying strings.
  • format! () macro. And pringln!!! () is similar, but returns a string instead of writing text to standard output.
  • Arrays and vectors of strings have two methods.concat() and.join(sep) that concatenate multiple strings into a new String.
let arr1: [&str; 3] = ["a1", "b2", "c3"]; println! ("{}", arr1.concat()); // a1b2c3 let arr2: [String; 3] = ["a11".to_string(), "b22".to_string(), "c33".to_string()]; println! ("{}", arr2.concat()); // a11b22c33 let vec1: Vec<&str> = vec! ["aa", "dd", "cc"]; println! ("{}", vec1.concat()); // aaddcc let vec2: [[i32; 2]; 2] = [[1, 2], [3, 4]]; println! (" {:? }", vec2.concat()); // [1, 2, 3, 4]Copy the code

Comparison of string equality

  • Strings support == and! = operator.
  • Two strings are equal as long as they contain the same characters in the same order. (Whether they point to the same address in memory or not)