通过引用修改 table 行时的奇怪行为
Strange behaviour when modifying table row via reference
我想编写一个导出 table 引用的方法。这是必需的,因为它的每一行都可以有自己的结构。所以我声明的类型是这样的:
... TYPE STANDARD TABLE OF REF TO data.
我认为如果我可以立即修改 table 的最后一行而不是单独的工作区只是为了追加,那将是一个好主意。
为什么这样做...
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
" ...
APPEND INITIAL LINE TO ei_lines ASSIGNING <lfs_struct>.
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
ASSIGN <lfs_struct>->* TO <lfs_target>.
...但这不是吗?
DATA: lo_struct TYPE REF TO data.
" ...
APPEND INITIAL LINE TO ei_lines REFERENCE INTO lo_struct.
CREATE DATA lo_struct TYPE (<lfs_field>-segnam).
ASSIGN lo_struct->* TO <lfs_target>.
With 'work' 我的意思是附加行的值确实发生了变化。如果我像在第二个示例中那样将某些内容分配给 <lfs_target>
,它会改变结构本身 - 但 table.
中的 而不是
显然我正在更改上一个示例的引用。但是为什么它与 Field-Symbols 一起工作呢?
您的代码使用字段符号而不使用数据对象的原因是因为这两者以不同的方式处理内存中的数据。 C++中也有类似的概念,虽然习惯了C++的ABAP中的命名有点混乱:
在 ABAP 中,字段符号有点像 C++ 中的引用(或者像 SAP 所说的取消引用的 C++ 指针)。它不为自己的数据分配内存,而是引用一些现有的字段/数据对象。将数据对象分配给字段符号后,如果您通过字段符号访问该数据对象,那么您永远不会与字段符号本身对话,而是直接与数据对象对话! (这是你案例中的关键部分,我们稍后会看到。)
现在,在您的第一个示例中,您创建了字段符号,它还没有执行任何操作:
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
只有在为内部 table 创建新行并将新分配的内存分配给字段符号 <lfs_struct>
后,字段符号才指向某些数据(table 行).然后你动态分配更多的内存:
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
现在你的内部 table ei_lines
指向新添加的 table 行(内存地址),你的字段符号也是如此。该内存地址又指向 CREATE DATA
中新创建的数据。需要注意的是,如前所述,您访问的不是字段符号本身,而是它所指的内存!
在第二个示例中但是您首先为新数据对象分配内存:
DATA: lo_struct TYPE REF TO data.
然后您再次为新的 table 行 (APPEND
) 分配新内存,并将对该内存地址的引用放入数据对象 lo_struct
。现在是有趣的部分:您动态创建另一个数据(对象)并将指向该新数据的指针保存到 lo_struct
中。因此现在 lo_struct
不再引用新的 table 行,而是引用 CREATE DATA
.
中新创建的数据
TL;DR 在第一个示例中,您 CREATE DATA
并将对该数据的引用保存到字段符号 <lfs_struct>
所指的对象中,这是 ei_lines
中新的 table 行。然而,在第二个示例中,您还创建了一个新的 table 行并通过 lo_struct
引用它,但是当您之后 CREATE DATA
时,您再次将对该新数据的引用存储到 lo_struct
,从而覆盖对新 table 行的原始引用。
我想编写一个导出 table 引用的方法。这是必需的,因为它的每一行都可以有自己的结构。所以我声明的类型是这样的:
... TYPE STANDARD TABLE OF REF TO data.
我认为如果我可以立即修改 table 的最后一行而不是单独的工作区只是为了追加,那将是一个好主意。
为什么这样做...
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
" ...
APPEND INITIAL LINE TO ei_lines ASSIGNING <lfs_struct>.
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
ASSIGN <lfs_struct>->* TO <lfs_target>.
...但这不是吗?
DATA: lo_struct TYPE REF TO data.
" ...
APPEND INITIAL LINE TO ei_lines REFERENCE INTO lo_struct.
CREATE DATA lo_struct TYPE (<lfs_field>-segnam).
ASSIGN lo_struct->* TO <lfs_target>.
With 'work' 我的意思是附加行的值确实发生了变化。如果我像在第二个示例中那样将某些内容分配给 <lfs_target>
,它会改变结构本身 - 但 table.
显然我正在更改上一个示例的引用。但是为什么它与 Field-Symbols 一起工作呢?
您的代码使用字段符号而不使用数据对象的原因是因为这两者以不同的方式处理内存中的数据。 C++中也有类似的概念,虽然习惯了C++的ABAP中的命名有点混乱:
在 ABAP 中,字段符号有点像 C++ 中的引用(或者像 SAP 所说的取消引用的 C++ 指针)。它不为自己的数据分配内存,而是引用一些现有的字段/数据对象。将数据对象分配给字段符号后,如果您通过字段符号访问该数据对象,那么您永远不会与字段符号本身对话,而是直接与数据对象对话! (这是你案例中的关键部分,我们稍后会看到。)
现在,在您的第一个示例中,您创建了字段符号,它还没有执行任何操作:
FIELD-SYMBOLS: <lfs_struct> TYPE REF TO DATA.
只有在为内部 table 创建新行并将新分配的内存分配给字段符号 <lfs_struct>
后,字段符号才指向某些数据(table 行).然后你动态分配更多的内存:
CREATE DATA <lfs_struct> TYPE (<lfs_field>-segnam).
现在你的内部 table ei_lines
指向新添加的 table 行(内存地址),你的字段符号也是如此。该内存地址又指向 CREATE DATA
中新创建的数据。需要注意的是,如前所述,您访问的不是字段符号本身,而是它所指的内存!
在第二个示例中但是您首先为新数据对象分配内存:
DATA: lo_struct TYPE REF TO data.
然后您再次为新的 table 行 (APPEND
) 分配新内存,并将对该内存地址的引用放入数据对象 lo_struct
。现在是有趣的部分:您动态创建另一个数据(对象)并将指向该新数据的指针保存到 lo_struct
中。因此现在 lo_struct
不再引用新的 table 行,而是引用 CREATE DATA
.
TL;DR 在第一个示例中,您 CREATE DATA
并将对该数据的引用保存到字段符号 <lfs_struct>
所指的对象中,这是 ei_lines
中新的 table 行。然而,在第二个示例中,您还创建了一个新的 table 行并通过 lo_struct
引用它,但是当您之后 CREATE DATA
时,您再次将对该新数据的引用存储到 lo_struct
,从而覆盖对新 table 行的原始引用。