(数组赋值)Array_a:=Array_b ( 积分: 50 )

  • 主题发起人 主题发起人 ddzhouqian
  • 开始时间 开始时间
D

ddzhouqian

Unregistered / Unconfirmed
GUEST, unregistred user!
如题:我想对两个相同大小的动态数组进行赋值,Array_a为全局变量,Array_b为局部变量
1.我的代码如下:
var Array_a:Array of Byte;
procedure TForm1.Button1Click(Sender: TObject);
var Array_b:Array of Byte;
begin
SetLength(Array_a,2);
Array_a[0]:=01;
Array_a[1]:=02;
SetLength(Array_b,2);
Array_b:=Array_a;//这句报错,编译不过去
end;
2.我在程序中还要对Array_a(全局变量)初始化
但我查了些资料,这样的赋值方式:Array_b:=Array_a只是进行别名引用.
也就是说如果我在此过程中再对Array_a(全局变量)初始化将会影响到Array_b中的值.
3.如果用循环是可以实现的,但我现在想用一简单方法实现,多谢各位参与解答,如果我没说清楚,请帮我修正,谢谢!
 
Array_b:=Array_a
这个是地址了,a和b的地址不一样,怎么赋值啊?数组的名称代表的是地址,记住这个。
直接copymemory来做吧。
 
move(Array_a[0], Array_b[0], Length(Array_a) * SizeOf(Array_a[0]));
 
to cqwty:
如果Array_a,Array_b在同一过程中的局部变量是可以这样操作的.
Array_b:=Array_a编译也能过的,但在执行后,如果对其中一变量进行再次赋值就另一个变量也会跟着变了,因为他们指向的是同一地址.
 
是这样的 Object Pascal 认为每个指针都是相异的, 为了把Array_b赋给Array_a你必须新建一个类型
例如
PByte = Array of Byte;
然后把 Array_a ,Array_b 都声明为PByte类型 就可以通过编译了
 
to cqwty,zhuangqr
我还是没搞明白,Array_b与@Array_b与@(Array_b[0])有什么区别
我刚试了下,值都不一样,好奇怪
不都是地址吗?
 
最简单也是最标准的动态数组复制方法:
Array_b:=Copy(Array_a);
 
@是取变量的地址的意思, Array_b是你声明的一个动态数组,而@Array_b是取这个数组的地址,而@Array_b[0]是取这个数组第一个元素的地址,它们当然是不一样的了.可以认为它们都是地址,但却是不同的地址
 
Delphi处理的内存主要有两种,堆和栈
使用的方法也有两种,值和引用

其中栈是程序控制的,不需要程序员人工创建和释放,比如简单类型就是定义在栈中,比如
var
i: Integer

在声明的时候因为i是简单类型,所以在栈中分配内存(分配了4个字节)
你不需要给创建i,也不需要释放i,这都由编译器来对栈进行操作
使用的方法是值引用就是说栈中的内存保存的是它本身的值
如上面的i的值就是它本身的值,@i则是它的指针Integer(@i)得到的整数是地址值
需要注意的是静态数组和Record都是简单类型,在栈中分配内存,而栈有最大值,好像默认是1M,所以尽量不要将非常大的静态数组和Record定义为静态数组

而复杂类型(Java中称为对象),比如类,动态数组,长字符串(string,AnsiString)等使用“引用”方式存取,声明的时候仅仅在栈上开辟一段内存(4个字节),里面保存的值是它实际内容的指针,而实际的内容保存在堆中
堆可以由程序员控制,大小仅仅取决于内存的大小。
比如声明一个动态数组
var
TmpArray: array of Byte;
那么仅仅在栈中自动分配了一个4字节的内存,里面是实际内容的指针,初始为nil
真正的内容保存在堆中,要程序员负责开辟内存和释放内存
比如你开辟了一段内存(使用标准函数SetLength)
SetLength(TmpArray, 2 * SizeOf(Byte));
这样就在堆中申请了2个字节的内存,内存的首地址保存在栈中TmpArray里,就是说你使用TmpArray来“引用”动态数组的实际内容
这时候Integer(TmpArray)显示的数字就是堆中内存地址
Integer(@TmpArray)显示的数字就是栈中保存指针的4个自己的内存的地址

结论
对于对象的赋值,Java和C#中有Clone方法,但Delphi中没有
我认为nicai_wgl的方法可行
 
楼上解释得太详细了,我又学到一招。
谁说大富翁没高手,这不是又出来一个。
 
楼上的过奖,我也是菜鸟一只

补充一句,在TPersistent中有三个方法
TPersistent = class(TObject)
private
procedure AssignError(Source: TPersistent);
protected
procedure AssignTo(Dest: TPersistent)
virtual;
public
procedure Assign(Source: TPersistent)
virtual;
end;
其中Public的方法Assigh就是用来进行对象赋值的,但是它是一个虚方法,调用了AssignTo。AssignTo也是一个虚方法,里面没有提供具体的实现过程。
这说明这两个方法可以被子类覆盖
我们可以改写这两个类进行对象的赋值
不过好像我也没有见到有谁在子孙类主动改写(override)这两个方法的
大多都是自己写代码实现
 
后退
顶部