如何将变量对象作为值参数传递
How to pass variable object as a value argument
我有一个自定义的数据类型,以及一个该类型的全局变量。我将这个全局变量作为参数传递给几个方法,变量的值似乎无意中改变了。
我发现所有对象都作为引用参数传递,即使未声明为 var 参数(或者我认为如此)也是如此。
所以我试图通过向我传递对象的所有方法引入局部变量来解决这个问题,然后将局部变量分配给参数,然后将对象参数声明为 const - 但值全局变量的 仍然在变化,我该如何克服这个问题?
{unit something}
interface
uses
SysUtils
type
ByteArr = Array of Byte;
Num = record
sign : byte;
int : ByteArr;
frac : ByteArr;
end;
function StrToNum(input : string):Num;
function NumToStr(input : Num):string;
function Dostuff(const a : Num):Num
implementation
function StrToNum(input : string):Num;
begin
//code to convert a string into 'Num' type
end;
function NumToStr(input : Num):string;
begin
//code to output a string version of a 'Num' input
end;
function Dostuff(const a : Num):Num
var
somevar : num;
begin
somevar := a;
code; //code to change value of 'somevar'
result := somevar;
end;
end.
{console program}
uses
something in 'something.pas';
var
globalvar : num;
begin
globalvar := StrToNum('2');
writeln(NumToStr(globalvar)); //shows 2
writeln(NumToStr(Dostuff(globalvar))); //shows correct value
writeln(numtostr(globalvar)); //no longer displays 2
end.
对象是指针类型。一些指针(对象副本)可以寻址相同的内存块,因此修改一个副本会影响其他副本。
您的问题定义不明确,但我怀疑您可能需要对象内容的 "deep copy" - 例如在 Assign
的帮助下 - 从 TPersistent
继承 class 并实现 AssignTo
方法。
动态数组是引用类型。您的类型 ByteArr
是动态数组,因此是引用类型。这种类型的变量赋值是引用赋值而不是值赋值。
考虑这段代码:
var
A, B: ByteArr;
....
SetLength(A, 1);
A[0] := 0;
B := A;
Writeln(A[0]);
B[0] := 42;
Writeln(A[0]);
这将输出
0
42
那是因为B := A
后的两个变量引用同一个数组。
使用Copy
创建一个新数组,它是第一个数组的副本:
B := Copy(A);
我有一个自定义的数据类型,以及一个该类型的全局变量。我将这个全局变量作为参数传递给几个方法,变量的值似乎无意中改变了。
我发现所有对象都作为引用参数传递,即使未声明为 var 参数(或者我认为如此)也是如此。
所以我试图通过向我传递对象的所有方法引入局部变量来解决这个问题,然后将局部变量分配给参数,然后将对象参数声明为 const - 但值全局变量的 仍然在变化,我该如何克服这个问题?
{unit something}
interface
uses
SysUtils
type
ByteArr = Array of Byte;
Num = record
sign : byte;
int : ByteArr;
frac : ByteArr;
end;
function StrToNum(input : string):Num;
function NumToStr(input : Num):string;
function Dostuff(const a : Num):Num
implementation
function StrToNum(input : string):Num;
begin
//code to convert a string into 'Num' type
end;
function NumToStr(input : Num):string;
begin
//code to output a string version of a 'Num' input
end;
function Dostuff(const a : Num):Num
var
somevar : num;
begin
somevar := a;
code; //code to change value of 'somevar'
result := somevar;
end;
end.
{console program}
uses
something in 'something.pas';
var
globalvar : num;
begin
globalvar := StrToNum('2');
writeln(NumToStr(globalvar)); //shows 2
writeln(NumToStr(Dostuff(globalvar))); //shows correct value
writeln(numtostr(globalvar)); //no longer displays 2
end.
对象是指针类型。一些指针(对象副本)可以寻址相同的内存块,因此修改一个副本会影响其他副本。
您的问题定义不明确,但我怀疑您可能需要对象内容的 "deep copy" - 例如在 Assign
的帮助下 - 从 TPersistent
继承 class 并实现 AssignTo
方法。
动态数组是引用类型。您的类型 ByteArr
是动态数组,因此是引用类型。这种类型的变量赋值是引用赋值而不是值赋值。
考虑这段代码:
var
A, B: ByteArr;
....
SetLength(A, 1);
A[0] := 0;
B := A;
Writeln(A[0]);
B[0] := 42;
Writeln(A[0]);
这将输出
0
42
那是因为B := A
后的两个变量引用同一个数组。
使用Copy
创建一个新数组,它是第一个数组的副本:
B := Copy(A);