/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html Concept: Clone Usage: clone from variable a value into new variable , not borrowing, not shadowing. let variable2 = variable1.clone() (heap-space1) (heap-space2) (data1) -> (data1) */ fn main() { let owner1 = String::from("I am saved only in one heap-space1, not others. Value in heap-space1 Not coped into heap-space2."); // owner let owner2 = owner1; // Move ownership (pointer only) from owner1 to owner2. Then owner1 not accsessable. Can't be used. //println!("owner1 {}", owner1); // NOT ACCESS, not-valid compiler mark this variable as not accsessable. Pointer (--> heap --> ['v' 'a' 'l' 'u' 'e']) moved in new owner2 // compiler: value borrowed here after move println!("Owner2: {}", owner2); /* ╔════════════════════════════════════════════════════════════════════════════╗ ║ MOVE ownership (Default Behavior) let owner2 = owner1; ║ ╚════════════════════════════════════════════════════════════════════════════╝ * owner1 ptr (pointer) moved into (owner2) STACK HEAP ┌─────────────────────┐ ┌──────────────────────────────────┐ │ owner1: String │ │ "I am saved only in one..." │ │ ┌─────────────────┐ │ │ [Offset: 0] │ │ │ ptr ────────────┼─┼──────────► │ [Length: 97 bytes] │ │ │ len: 97 │ │ │ [Capacity: 97] │ │ │ cap: 97 │ │ └──────────────────────────────────┘ │ └─────────────────┘ │ └─────────────────────┘ │ │ let owner2 = owner1; (MOVE: transfer ownership) │ ▼ ┌─────────────────────┐ ┌──────────────────────────────────┐ │ owner1: ❌ INVALID │ │ "I am saved only in one..." │ │ (moved out) │ │ [Same address1 in memory] │ └─────────────────────┘ └──────────────────────────────────┘ ┌─────────────────────┐ │ owner2: String │ │ ┌─────────────────┐ │ (address1) │ │ ptr ────────────┼─┼──────────► (points to SAME address1 heap allocation) │ │ len: 97 │ │ │ │ cap: 97 │ │ │ └─────────────────┘ │ └─────────────────────┘ (VALID: still accessible) */ // But with "Clone" we can not just move ownership, we can copy value from heap, to new memory area (new heap address space) let owner_1 = String::from("I am saved in 2 heap-spaces. (I am a copy from heap-space1, if you see me in heap-space2)"); // ACCESSABLE! Valid, Not shaddowed. Compiler not mark this. Ownership not moved. let owner_2 = owner_1.clone(); // Clone heap-space1 to new heap-space2 (copy a value, not borrowing, NOT mark owner_1 to not accsessable) println!("heap-space1: {}", owner_1); // valid println!("heap-space2: {}", owner_2); // valid /* ╔════════════════════════════════════════════════════════════════════════════╗ ║ CLONE (Deep Copy) .clone() ║ ╚════════════════════════════════════════════════════════════════════════════╝ STACK HEAP (Heap-space1) Pointers point to 0x1000 and 0x2000 ┌─────────────────────┐ ┌──────────────────────────────────┐ │ owner_1: String │ │ "I am saved in 2 heap-spaces..." │ │ ┌─────────────────┐ │ │ [Address: 0x1000] │ │ │ ptr ────────────┼─┼──────────► │ [Length: 99 bytes] │ │ │ len: 99 │ │ │ [Capacity: 99] │ │ │ cap: 99 │ │ └──────────────────────────────────┘ │ └─────────────────┘ │ └─────────────────────┘ │ │ let owner_2 = owner_1.clone(); (CLONE: deep copy heap data) │ ▼ [After] Heap-space1 Pointers point to 0x1000 and 0x2000 ┌─────────────────────┐ ┌──────────────────────────────────┐ │ owner_1: String ✓ │ │ "I am saved in 2 heap-spaces..." │ │ ┌─────────────────┐ │ │ [Address: 0x1000] ◄── ORIGINAL │ │ │ ptr ────────────┼─┼──────────► │ [Length: 99 bytes] │ │ │ len: 99 │ │ │ [Capacity: 99] │ │ │ cap: 99 │ │ └──────────────────────────────────┘ │ └─────────────────┘ │ └─────────────────────┘ (VALID: still accessible) Heap-space2 Pointers point to 0x2000 and 0x3000 ┌─────────────────────┐ ┌──────────────────────────────────┐ │ owner_2: String ✓ │ │ "I am saved in 2 heap-spaces..." │ │ ┌─────────────────┐ │ │ [Address: 0x2000] ◄── COPY │ │ │ ptr ────────────┼─┼──────────► │ [Length: 99 bytes] │ │ │ len: 99 │ │ │ [Capacity: 99] │ │ │ cap: 99 │ │ └──────────────────────────────────┘ │ └─────────────────┘ │ └─────────────────────┘ (VALID: still accessible) */ }