Allocating an empty non null associative arary
WebFreak001
d.forum at webfreak.org
Tue Mar 31 06:51:16 UTC 2020
On Tuesday, 31 March 2020 at 02:51:11 UTC, Superstar64 wrote:
> I want to be modify an associative array by reference from
> another function. However null associative arrays are pass by
> value. How do I generically create an empty associative array?
> ---
> import std.stdio;
>
>
> void addElement(int[int] data){
> data[0] = 0;
> }
>
> void nonempty() {
> int[int] items = [1 : 1];
> writeln(items); // [1 : 1]
> addElement(items);
> writeln(items); // [0 : 0, 1 : 1]
> }
>
> void empty(){
> int[int] items = null;
> writeln(items); // []
> addElement(items);
> writeln(items); // []
> }
>
> void main(){
> nonempty();
> empty();
> }
> ---
This doesn't only happen with null, you will notice that that
function will eventually not add anything if you only add values.
This is because by adding values you might reallocate the map at
some other place in memory and because it's not ref, the caller
won't have the map point to the new reference and still only have
the old data.
Setting an existing key shouldn't reallocate, though it's not
exactly specified but it hints towards it:
https://dlang.org/spec/hash-map.html#construction_assignment_entries
So basically if you plan to add or remove items from your map, it
could reallocate your memory, so you need to pass your argument
by ref, so it updates the caller reference.
// use when inserting or updating
void addElement(scope ref int[int] data) {
data[0] = 1;
}
// use only when updating existing keys (though you might also
consider using ref anyway)
void changeElement(scope int[int] data) {
data[0] = 2;
}
// use for only reading
int readElement(scope const int[int] data) {
return data[0];
}
The ref signals the caller that the passed in data will be
modified. It's like passing pointers, but the value cannot be
null.
The scope signals the caller that you don't escape the reference
outside the function, so you can be sure the memory won't be
altered after the function has finished. This is especially
enforced if you pass -dip1000.
The const signals the caller that you won't modify the data. If
you use const, you need to be very strict with it and use it in
all your functions consistently, also adding const (or preferably
inout) to member functions of structs and classes not modifying
their data. (like getters) - You might otherwise need to do ugly
casts to remove the const to hack around a function definition
which might break the correctness of your program. But if you can
do const for your parameters, definitely add it.
The attributes are both for good documentation but also to
enforce correct usage by the compiler.
More information about the Digitalmars-d-learn
mailing list