I noticed that a library I'm using frequently returns []const u8 instead of []u8 when it allocates memory and the caller is responsible for freeing it.
Should a function return a mutable slice []u8
when the data is owned by the caller and must be freed?
Example
fn prefixString(
allocator: std.mem.Allocator,
string: []const u8,
prefix: []const u8
) ![]u8 {
return std.mem.concat(allocator, u8, &[_][]const u8{ prefix, string });
}
Here, prefixString returns a mutable slice of bytes, just like its underlying function, std.mem.concat
.
I noticed that a library I'm using frequently returns []const u8 instead of []u8 when it allocates memory and the caller is responsible for freeing it.
Should a function return a mutable slice []u8
when the data is owned by the caller and must be freed?
Example
fn prefixString(
allocator: std.mem.Allocator,
string: []const u8,
prefix: []const u8
) ![]u8 {
return std.mem.concat(allocator, u8, &[_][]const u8{ prefix, string });
}
Here, prefixString returns a mutable slice of bytes, just like its underlying function, std.mem.concat
.
- 1 in your opinion, why should it (and not) in context? or can this be universally answered? Please document the exact zig version you ask about. edit – hakre Commented Feb 17 at 19:15
1 Answer
Reset to default 1While it can be argued that it all depends on the design decisions of the library developers, it's indeed better to return []T
instead of []const T
when the caller owns the memory and needs to free it.
The const
provides a way to express restrictions in the API, that can protect against certain errors.
But in this case, the restriction isn't real, and the library users may have to cast away the const
to archive their goals.