gpt4 book ai didi

delphi - 为什么编译器坚持我的函数是内联的,而实际上它不是?

转载 作者:行者123 更新时间:2023-12-03 15:21:04 31 4
gpt4 key购买 nike

为什么我会得到

[DCC Error] ProjectCOWArray.dpr(23): E2426 Inline function must not have asm block

program ProjectCOWArray;

{$APPTYPE CONSOLE}

{$R *.res}

type
PRefCount = ^TRefCount;
TRefCount = array[0..1] of integer;


TCOWArray<T> = record
private
fData: TArray<T>;
private
procedure IncRefCount; <<-- not inline
end;


{ TCOWArray<T> }

procedure TCOWArray<T>.IncRefCount;
asm
{$if defined(win32)}
mov eax,fData;
lock inc dword ptr [eax - 8];
{$ifend}
{$if defined(win64)}
mov rax,fData;
lock inc dword ptr[rax -12];
{$ifend}
end;

begin
end.

Delphi XE2没有AtomicIncrement,那么如何解决这个问题?
它想保留汇编器,因为否则我无法使用 lock 前缀,并且我不想使用 InterlockedIncrement 因为那是一个 WinAPI 函数,我不希望那种开销。

最佳答案

这是因为泛型功能是在内联引擎之上实现的。适用于内联函数的相同限制也适用于泛型函数。编译器编写者只是没有采取额外的步骤来使错误消息特定于泛型而不是内联函数。

我认为,对于没有 AtomicIncrement 内在函数的 Delphi 版本,调用 InterlockedIncrement 可能是您的最佳选择。或者,创建您自己的 AtomicIncrement 版本,该版本仅在不包含它的 Delphi 版本中定义。该函数可以用 asm 编写。嗯,显然它必须用 asm 编写。

{$IFNDEF AtomicFunctionsAvailable}
function AtomicIncrement(var Target: Integer): Integer;
asm
....
end;
{$ENDIF}

或者正如@TLama建议的那样,您可以使用System.SyncObjs单元中的TInterlocked来提供原子操作。

尽管如此,我认为没有必要以这种方式干预内部结构。每当写入数组时,通过调用 SetLength(...) 来实现写入数组的副本。例如,这是一个非常简单的写数组复制实现:

unit COWArray;

interface

type
TCOWArray<T> = record
private
FItems: TArray<T>;
function GetLength: Integer;
procedure SetLength(Value: Integer);
function GetItem(Index: Integer): T;
procedure SetItem(Index: Integer; const Value: T);
public
class function New(const Values: array of T): TCOWArray<T>; static;
property Length: Integer read GetLength write SetLength;
property Items[Index: Integer]: T read GetItem write SetItem; default;
end;

implementation

function TCOWArray<T>.GetLength: Integer;
begin
Result := System.Length(FItems);
end;

procedure TCOWArray<T>.SetLength(Value: Integer);
begin
System.SetLength(FItems, Value); // SetLength enforces uniqueness
end;

function TCOWArray<T>.GetItem(Index: Integer): T;
begin
Result := FItems[Index];
end;

procedure TCOWArray<T>.SetItem(Index: Integer; const Value: T);
begin
System.SetLength(FItems, System.Length(FItems)); // SetLength enforces uniqueness
FItems[Index] := Value;
end;

class function TCOWArray<T>.New(const Values: array of T): TCOWArray<T>;
var
i: Integer;
begin
System.SetLength(Result.FItems, System.Length(Values));
for i := 0 to high(Values) do
Result.FItems[i] := Values[i];
end;

end.

关于delphi - 为什么编译器坚持我的函数是内联的,而实际上它不是?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24286088/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com