I am trying to remove an item from an array.
The array is not dynamic!
I found many examples on how to do it for the dynamic variant but none for the static.
example from delphi:
var
A: array of integer;
begin
...
A:=[1,2,3,4];
Delete(A,1,2); //A will become [1,4]
...
end;
example from another site:
type
TIntArray = array of Integer;
procedure DeleteArrayElement(var AArray: TIntArray; const AIndex: Integer);
begin
Move(AArray[AIndex + 1], AArray[AIndex], SizeOf(AArray[0]) * (Length(AArray) - AIndex - 1));
SetLength(AArray, Length(AArray) - 1);
end;
...
//call via
DeleteArrayElement(IntArray, 3);
...
My array is defined as 0 .. 11 so this is not dynamic(i guess)?
When I try to use the SetLength function it says incompatible types.
Any idea how to solve this?
When you declare a static array you tell the compiler that the memory for the whole array should be allocated and retained until the program is terminated (if allocated in global space).
You cannot change the size of a static array. This is the purpose why dynamic arrays are there in Delphi.
The Embarcadero documentation for static arrays says:
If you create a static array but don't assign values to all its
elements, the unused elements are still allocated and contain random
data; they are like uninitialized variables.
Related
Does setting a local dynamic array's length to zero (when it's no longer needed) have memory usage benefits?
For example:
var
MyArray : array of string;
begin
<filling my array with a lot of items....>
<doing some stuffs with MyArray>
//from here on, MyArray is no more needed, should I set its length to zero?
SetLength(MyArray, 0);
<doing other stuffs which doesn't need MyArray...>
end;
In Delphi, dynamic arrays are reference-counted.
Thus, if you do
MyArray := nil;
or
Finalize(MyArray);
or
SetLength(MyArray, 0);
the variable MyArray will no longer point to the dynamic array heap object, so its reference count will be reduced by 1. If this makes the reference count drop to zero, meaning that no variable points to it, it will be freed.
Example 1
So in
var
a: array of Integer;
begin
SetLength(a, 1024*1024);
// ...
SetLength(a, 0);
// ...
end
you will free up the memory on SetLength(a, 0), assuming a is the only variable pointing to this heap object.
Example 2
var
b: TArray<Integer>;
procedure Test;
var
a: TArray<Integer>;
begin
SetLength(a, 1024*1024);
b := a;
SetLength(a, 0);
// ...
end
SetLength(a, 0) will not free up any memory, because b is still referring to the original array. It will reduce the reference count from 2 to 1, though.
Example 3
And, of course, in
var
a: array of Integer;
begin
SetLength(a, 1024*1024);
// ...
SetLength(a, 0);
end
the last call to SetLength is completely unnecessary, since the local variable a will go out of scope on the next line of code anyway, which also reduces the refcount of the heap object.
Yes, when you set the length of a dynamic array to zero, the memory it is using is released back onto the available heap memory if no other variable/object is referencing the memory (not necessarily back to Windows memory, so you may not see the benefit in Task Manager, but it'll take longer for your Delphi program to need to allocate additional memory from Windows since it will first use the available heap memory, to which you have added the size of "MyArray").
I want to pass reference of an array to a function that needs the length of array. I want to know if I have to pass its length as well or I can retrieve it from the array reference.
uses
Vcl.Dialogs, System.SysUtils, System.Types;
type
IntegerArray = array[0..$effffff] of Integer; // defined in System
PIntegerArray = ^IntegerArray; // defined in System
procedure Foo(const P: PIntegerArray);
begin
ShowMessage(IntToStr(Length(P^)));
end;
const
A: array[0..2] of Integer = (1, 2, 3);
var
B: TIntegerDynArray;
initialization
Foo(#A);
B := [4, 5, 6];
Foo(#B[0]);
end.
To accomplish this, you need to declare an open array parameter:
procedure Foo(const A: array of integer);
begin
ShowMessage('Length of array:'+IntToStr(High(A)+1));
end;
Pass both dynamic and static arrays to the procedure, and the arrays length is given by System.High.
Open array : The value, of type Integer, giving the number of elements in the actual parameter, minus one.
Your question amounts to the following:
Given the address of the first element of an array, which could be either static or dynamic, can I find the length of that array?
The answer is no. There are two factors in your way.
You can't tell whether the array is dynamic or static.
Even if you knew the array was static, you would not be able to find its length without compile time knowledge of its type.
I need an array, that is optimized for one-time-initialization at runtime, with a given length. So memory should be allocated at runtime, but I don't need to change its length.
Is there a array-type other than the pure dynamic array? (it seems to be not the optimal choice for this task)
Bonus would be, if the initialized array is indexable via pointer-iteration, so all it's elements are allocated consecutive in memory.
Is this all just a daydream of a non-experienced programmer, or is there a possibility to achieve this?
I could imagine to do this with manual memory allocation, but maybe there's another way.
Edit:
My main concern is the reading and writing speed of the array.
Just use an external Count: integer variable, and use the dynamic array length as the "capacity" of the array. It would avoid most memory allocation, if the initial capacity of the array is well defined.
In practice, TList<T>, as defined in the System.Generics.Collections unit, is using this scheme: it stores internally an array, but it has its own Count property. I suspect this is what you were looking for.
For a more low-level stuff, with more features (like JSON or binary serialization, or fast lookup via a hash of one or several properties), you may take a look at our TDynArray dynamic array wrapper. Those are just wrappers on existing dynamic arrays, not data holder like TList<T>. And they work from Delphi 5 or older, and also FPC.
You can encapsulate what you desire in a generic type. Like this:
type
TFixedLengthArray<T> = record
strict private
FItems: TArray<T>;
FLength: Integer;
function GetItem(Index: Integer): T; inline;
procedure SetItem(Index: Integer; const Value: T); inline;
public
property Length: Integer read FLength;
property Items[Index: Integer]: T read GetItem write SetItem; default;
class function New(const Values: array of T): TFixedLengthArray<T>; static;
end;
{ TFixedLengthArray<T> }
class function TFixedLengthArray<T>.New(const Values: array of T): TFixedLengthArray<T>;
var
i: Integer;
begin
Result.FLength := System.Length(Values);
SetLength(Result.FItems, Result.FLength);
for i := 0 to Result.FLength-1 do begin
Result.FItems[i] := Values[i];
end;
end;
function TFixedLengthArray<T>.GetItem(Index: Integer): T;
begin
Result := FItems[Index];
end;
procedure TFixedLengthArray<T>.SetItem(Index: Integer; const Value: T);
begin
FItems[Index] := Value;
end;
Create a new one like this:
var
MyArray: TFixedLengthArray<Integer>;
....
MyArray: TFixedLengthArray<Integer>.New([1, 42, 666]);
Access items like this:
for i := 0 to MyArray.Length-1 do
Writeln(MyArray[i]);
This just wraps a dynamic array. Elements are contiguous. The length of the array is determined once and for all then a new instance is created.
One thing to watch out for here is that the type will behave like a reference type since its data is stored in a reference type. That is, the assignment operator on this type will behave in the same manner as dynamic array assignment.
So if we have two variables of this type, arr1 and arr2 then the following occurs:
arr1 := arr2;
arr1[0] := 42;
Assert(arr2[0] = 42);
If you wanted to make the type behave like a true value then you would implement copy-on-write inside SetItem.
Update
Your edit to the question changes is significantly. It seems that you are in fact concerned more with performance than encapsulation.
The inlining of the item accessor methods in the above type means that the performance characteristics should be close to that of an array. The access will still be O(1), but it is quite plausible that the inliner/optimiser is weak and fails to emit the most optimal code.
Before you decide that you must use arrays to obtain the absolute ultimate performance, do some real world benchmarking. It seems to me to be quite unlikely that the code to read/write from an array is really a bottleneck. Most likely the bottleneck will be what you then do with the values in the array.
I read somewhere that Ada allows a function only to return a single item. Since an array can hold multiple items does this mean that I can return the array as a whole or must I return only a single index of the array?
Yes, an Ada function can return an array - or a record.
There can be a knack to using it, though. For example, if you are assigning the return value to a variable, the variable must be exactly the right size to hold the array, and there are two common ways of achieving that.
1) Fixed size array - cleanest way is to define an array type, e.g.
type Vector is new Array(1..3) of Integer;
function Unit_Vector return Vector;
A : Vector;
begin
A := Unit_Vector;
...
2) Unconstrained array variables.
These are arrays whose size is determined at runtime by the initial assignment to them. Subsequent assignments to them will fail unless the new value happens to have the same size as the old. The trick is to use a declare block - a new scope - so that each assignment to the unconstrained variable is its first assignment. For example:
for i in 1 .. last_file loop
declare
text : String := Read_File(Filename(i));
-- the size of "text" is determined by the file contents
begin
-- process the text here.
for j in text'range loop
if text(j) = '*' then
...
end loop;
end
end loop;
One warning : if the array size is tens of megabytes or more, it may not be successfully allocated on the stack. So if this construct raises Storage_Error exceptions, and you can't raise the stack size, you may need to use access types, heap allocation via "new" and deallocation as required.
Yes, an Ada function can return an array. For example, an Ada String is "A one-dimensional array type whose component type is a character type." Several of the functions defined in Ada.Strings.Fixed—including Insert, Delete, Head, Tail and Trim—return a String.
How do you allocate an array in Go with a run-time size?
The following code is illegal:
n := 1
var a [n]int
you get the message prog.go:12: invalid array bound n (or similar), whereas this works fine:
const n = 1
var a [n]int
The trouble is, I might not know the size of the array I want until run-time.
(By the way, I first looked in the question How to implement resizable arrays in Go for an answer, but that is a different question.)
The answer is you don't allocate an array directly, you get Go to allocate one for you when creating a slice.
The built-in function make([]T, length, capacity) creates a slice and the array behind it, and there is no (silly) compile-time-constant-restriction on the values of length and capacity. As it says in the Go language specification:
A slice created with make always allocates a new, hidden array to which the returned slice value refers.
So we can write:
n := 12
s := make([]int, n, 2*n)
and have an array allocated size 2*n, with s a slice initialised to be the first half of it.
I'm not sure why Go doesn't allocate the array [n]int directly, given that you can do it indirectly, but the answer is clear: "In Go, use slices rather than arrays (most of the time)."