Pass by value semantics

I think what they mean is something like this:

const std = @import("std");
const mem = std.mem;

const LargeItem = struct {
    data: [128]u8, // Large enough that a compiler might want to pass it by pointer
};

fn ownAppend(list: *std.ArrayList(LargeItem), gpa: mem.Allocator, item: LargeItem) !void {
    // This call might force the ArrayList to grow, freeing the old memory block
    try list.ensureUnusedCapacity(gpa, 1);
    // If the memory moved, 'item' is now a dangling pointer
    list.appendAssumeCapacity(item);
}

pub fn main(init: std.process.Init) !void {
    var list: std.ArrayList(LargeItem) = .empty;
    defer list.deinit(init.gpa);

    try list.append(init.gpa, LargeItem{ .data = [_]u8{42} ** 128 });
    // Value semantics guarantee this should be a safe snapshot copy.
    try ownAppend(&list, init.gpa, list.items[0]);
}

If you pass by pointer(reference) nothing will be copied onto the stack(except if you dereference it later onto a stack variable).

Honestly I don’t understand what you mean by that.

1 Like