2013-09-30 12 views
9

Delphi ha:posso forzare `const` di passare per riferimento (aka il parametro mancante` tale dicitura)

var: passare riferimento; parametro è sia input che output.
out: passaggio per riferimento; il parametro è solo in uscita.
const: passare da ..... beh dipende; parametro è solo input.
in: passare per riferimento; il parametro è solo input e non verrà modificato non c'è "in".

Non mi interessa che there is no spoon, ma mi manca in; considerando il seguente codice, c'è un modo più pulito per farlo?

type TFastDiv = record 
strict private 
    FBuffer: Int64; 
    other fields 
.... 

//Must be `var` because `const` would pass a Int64 by value 
//      ||| 
//      VVV 
function DivideFixedI32(var Buffer: Int64; x: integer): integer; 
asm 
    mov r9,rcx     
    imul dword ptr[rcx] // do stuff with the buffer 
    .. 
    mov  ecx, [r9+4] // do other stuff with the rest of the buffer 

{Modifica del codice a imul ecx;...;shr r9,32;mov ecx,r9d permetterebbe passaggio per valore, ma supponiamo che il codice non deve essere modificato.}

class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer; 
begin 
    Result:= DivideFixedI32(Int64((@buffer.FBuffer)^), abs(x)); <<-- Ugly 
    if (x < 0) then Result:= - Result; 
end; 

DivideFixed non cambierà mai il buffer. L'intero punto della routine è che buffer è un valore precalcolato che non cambia.

Nell'operatore di classe dichiaro il buffer come const, poiché il record non deve cambiare.

La domanda è:
se insisto sulla proclamazione del parametro buffer in IntDivide come const c'è un modo più pulito di codifica o sono io bloccato nel pointer_to/points_to incidere?

+0

Cosa significa "in"? Quello che manca davvero è C++ 'const MyType & value' –

+0

' in' sarebbe l'opposto di 'out', passa per riferimento ma il parametro è garantito per non cambiare; e sì, un puntatore (noto anche come pass_by_reference) che non verrà modificato all'interno della routine. – Johan

risposta

13

versioni di compilatore recenti (da XE3 poi) supportano il [Ref] decoratore:

procedure Foo(const [Ref] Arg1: Integer; [Ref] const Arg2: Byte); 

Esempio adattato da the documentation, che sottolinea la [Ref] può andare prima o dopo la parola chiave const.

+3

+1 molto bello. Sai quali compilatori supportano questo? I compilatori desktop fanno così? –

+0

OK, sono stato in grado di controllarlo da solo sul compilatore desktop XE5 e [ref] è implementato lì. Quindi, mi aspetto che sia implementato ovunque. –

+1

@DavidHeffernan XE3 sembra essere il primo (appena provato), e sì, anche i compilatori desktop. –

4

L'unica opzione (pre Delphi XE3) se si desidera garantire il pass-by-reference, è passare qualcosa di grande.
ossia maggiore di sizeof (puntatore)

type TFastDiv = record 
strict private 
    FBuffer: Int64; <<-- make sure this is the first member 
    other fields 
.... 

function DivideFixedI32(const Buffer: TFastDiv; x: integer): integer; 
... 
class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer; 
begin 
    Result:= DivideFixedI32(buffer, abs(x)); 

Questa linea nella Delphi help file:

insiemi, record e matrici statiche di 1, 2 o 4 byte vengono passati a 8 bit, Valori a 16 bit e 32 bit. Set, record e array statici più grandi vengono passati come puntatori a 32 bit al valore. Un'eccezione a questa regola è che i record vengono sempre passati direttamente sullo stack sotto le convenzioni cdecl, stdcall e safecall; la dimensione di un record passato in questo modo viene arrotondata al più vicino limite di doppia parola.

è fuorviante e dovrebbe essere cambiata a/letto come:

Set, record e le matrici statiche fino a sizeof (pointer) vengono passati come 8-bit, 16-bit, e Valori a 32 bit (valori a 64 bit su x64). Set, record e array statici più grandi di SizeOf (Pointer) vengono passati come puntatori al valore. Un'eccezione a questa regola è che i record vengono sempre passati direttamente sullo stack sotto le convenzioni cdecl, stdcall e safecall; la dimensione di un record passato in questo modo viene arrotondata al limite più vicino di SizeOf (puntatore).

Problemi correlati