Applying R to Lifestyle and Brain Health Research
University of Kansas Medical Center
August 12, 2026
Behind the scenes R creates a vector object of values c(1, 2, 3) and binds it to a name x with an object address of 0x8d526b868.
Modifying y creates a new object that is a copy of 0x8d526b868 and has a new object address of 0x8d56e6968.
We can see when an object gets copied with base::tracemem()
The same rules for copying apply to function calls.
Once f() completes, x and z will point to the same object.
Elements of lists can also point to objects, but copy-on-modify differs from variables in that a shallow copy is created.
A list stores references to the values rather than the values. This is important to know for understanding what happens when we modify a list.
Using the ref() function from the lobstr package shows the shared bindings across l1 and l2.
Data frames are lists of vectors and copy-on-modify works differently for columns and rows.
Columns
Only the modified column is changed.
Rows
Every column is modified and must be copied.
R uses a global string pool where each element in a character vector points to a unique string in the pool.
The global string pool has an impact on the amount of memory a character vector uses, but can otherwise be thought of similarly to numeric vectors.
Use lobstr::obj_size to find out how much memory an object takes.
The elements of a list are references to the values. Storing x three times is the size of an empty list with three NULL elements.
References make it more challenging to think about the size of individual objects. The object size only equals the combined object size if there are no shared values.
vegetables <- c("broccoli", "broccoli", "broccoli")
fruits_or_vegetables <- c("apple", "broccoli", "apple")
obj_size(fruits, vegetables)
#> 280 B
obj_size(fruits) + obj_size(vegetables)
#> 280 B
obj_size(fruits, fruits_or_vegetables)
#> 280 B
obj_size(fruits) + obj_size(fruits_or_vegetables)
#> 336 BR has the ability to represent some vectors compactly. For example, using the : when providing a numeric range stores the first and last number only such that every sequence is always the same size.
R environments are modified-in-place rather than copied-on-modify. When you modify an environment, all existing bindings to that environment continue to have the same reference.
After running this code, we have two numeric objects not bound to a name. The garbage collector (GC) frees up memory by deleting R objects that are no longer used. The garbage collector runs automatically when R needs more memory to create new objects or manually using the gc function. You can also check the memory used using the lobstr::mem_used function.
R for Lifestyle and Brain Health (R-LAB)