用 (*it).m 还是 it->m

探讨了C++中迭代器成员访问的两种方式:指针成员选取运算符(it->m)和解引用及点号成员选取运算符((*it).m),并推荐使用后者以避免潜在问题。
用 (*it).m 还是 it->m

摘自《Extended STL》

标准库要求,所有值类型为聚合类型的迭代器必须支持指针成员选取运算符(operator ->()),下面是使用该运算符的示例代码:

struct X
{
int x;
};

some_iterator<X> si = . . .
some_iterator<X> si2 = . . .
some_iterator<X> end = . . .

if( end != si &&
end != si2)
{
si->x = si2->x;
}

标准(C++-03: 24.1.1;1)要求,对一个迭代器应用指针成员选取运算符,在语义上等同于先对其应用解引用运算符,再应用点号成员选取运算符,即it->m与(*it).m等效。

可惜,使用该运算符会遇上麻烦。

假设我们有一个容器类型C,它的实例保存智能指针类型P的实例,P用于管理对象生存期。P上定义了一个release()方法用于提早释放对象。进一步假设,被P管理的类型T上也定义了一个release()方法。在下面代码片断中,我们希望通过该容器的迭代器类型I的一个实例,调用T::release()方法:

C cont = . . .
I it = cont.begin();
it->release();

不幸的是,这段代码调用的不是T::release()方法,它调用的是P::release()方法,从而销毁了T的实例。当我们再次使用cont这个容器的时候,就可能遇到各种奇怪的问题,以下代码才是真正实现我们想法的代码:

C cont = . . .
I it = cont.begin();
it->->release();

可是C++并不支持这样的语句,且理由充分。(想象一下,如果C++支持这样的语句,"模糊C++代码"大赛上,会有多少参赛代码,争着在一条语句中塞进最多的operator->()调用!)

为使C++满足我们的想法,我们必须放弃成员选取运算符而转用解引用运算符,就像以下代码示例中一样:

C cont = . . .
I it = cont.begin();
(*it)->release();

这是迭代器语法中恼人的小缺点。

在迭代器中支持指针成员选取运算符,没什么实质的意义,而仅仅是语法糖。我认为标准中将这规定为迭代器概念的一个特性是严重的错误。在我的日常工作中,除了仅有几个特例外,我完全避免使用迭代器的指针成员选取运算符,而使用解引用和点号成员选取运算符。我建议你也这么做。

Tip: Prefer iterator dereference and the dot member selection operator ((*it).m) over the pointer member selection operator (it->m).

提示: 使用解引用及点号成员选择运算符((*it).m)代替指针成员选择运算符(it->m)。

(转载请注明来源于金庆的专栏)
以下程式兩組radion 只能兩擇一,請修正。report zt . type-pools: vrm, slis, soi,ole2. *--------------------------------------------------------------------- * 1. 內表結構 *--------------------------------------------------------------------- TYPES: BEGIN OF ty_data,          lifnr       TYPE char10,   " 供應商編號          check1(1)   TYPE c,          bank1_text  TYPE char40,          check2(1)   TYPE c,          bank2_text  TYPE char40,        END OF ty_data. DATA: gt_data     TYPE STANDARD TABLE OF ty_data,       gs_data     TYPE ty_data. *--------------------------------------------------------------------- * 2. LVC 欄位目錄 / Layout *--------------------------------------------------------------------- DATA: gt_fieldcat TYPE lvc_t_fcat,       gs_fieldcat TYPE lvc_s_fcat,       gs_layout   TYPE lvc_s_layo. DATA: gt_dropdown TYPE lvc_t_drop,       gs_drop     TYPE lvc_s_drop. *--------------------------------------------------------------------- * 3. 從 ZVBANK 撈資料並組合 BANK TEXT *--------------------------------------------------------------------- FORM get_data_from_zvbank.   DATA: lt_zvbank TYPE TABLE OF zvbank,         ls_zvbank TYPE zvbank.   " 直接抓 ZVBANK   SELECT * FROM zvbank INTO TABLE lt_zvbank UP TO 50 ROWS.   LOOP AT lt_zvbank INTO ls_zvbank.     CLEAR gs_data.     " LIFNR 用 BANKL 當範例顯示     gs_data-lifnr = ls_zvbank-bankl.     " BANK1_TEXT / BANK2_TEXT 都用 BANKL + BANKN 組合     CONCATENATE ls_zvbank-bankl ls_zvbank-bankn                 INTO gs_data-bank1_text SEPARATED BY space.     CONCATENATE ls_zvbank-bankl ls_zvbank-bankn                 INTO gs_data-bank2_text SEPARATED BY space.     APPEND gs_data TO gt_data.   ENDLOOP. ENDFORM. *--------------------------------------------------------------------- * 4. 建立欄位目錄 *--------------------------------------------------------------------- FORM build_fieldcat.   CLEAR gt_fieldcat.   CLEAR gs_fieldcat.   gs_fieldcat-fieldname = 'LIFNR'.   gs_fieldcat-scrtext_m = '供應商'.   APPEND gs_fieldcat TO gt_fieldcat.   CLEAR gs_fieldcat.   gs_fieldcat-fieldname = 'CHECK1'.   gs_fieldcat-checkbox  = 'X'.   gs_fieldcat-edit      = 'X'.   gs_fieldcat-scrtext_m = '選項 1'.   APPEND gs_fieldcat TO gt_fieldcat.   CLEAR gs_fieldcat.   gs_fieldcat-fieldname = 'BANK1_TEXT'.   gs_fieldcat-scrtext_m = '銀行1說明'.   APPEND gs_fieldcat TO gt_fieldcat.   CLEAR gs_fieldcat.   gs_fieldcat-fieldname = 'CHECK2'.   gs_fieldcat-checkbox  = 'X'.   gs_fieldcat-edit      = 'X'.   gs_fieldcat-scrtext_m = '選項 2'.   APPEND gs_fieldcat TO gt_fieldcat.   CLEAR gs_fieldcat.   gs_fieldcat-fieldname = 'BANK2_TEXT'.   gs_fieldcat-scrtext_m = '銀行2說明'.   APPEND gs_fieldcat TO gt_fieldcat. ENDFORM. *--------------------------------------------------------------------- * 5. Layout 設定 *--------------------------------------------------------------------- FORM set_layout.   CLEAR gs_layout.   gs_layout-zebra = 'X'.         " 交錯底色   gs_layout-cwidth_opt = 'X'.    " 欄寬最佳化 ENDFORM. *--------------------------------------------------------------------- * 7. USER_COMMAND:兩組互斥 *--------------------------------------------------------------------- FORM user_command USING r_ucomm LIKE sy-ucomm                       rs_selfield TYPE slis_selfield.   DATA lv_index TYPE sy-tabix.   IF r_ucomm = 'ENTER' OR r_ucomm = '&IC1'.     " --- CHECK1 互斥     CLEAR lv_index.     LOOP AT gt_data INTO gs_data.       IF gs_data-check1 = 'X' AND lv_index IS INITIAL.         lv_index = sy-tabix.       ELSEIF gs_data-check1 = 'X' AND NOT lv_index IS  INITIAL.         gs_data-check1 = space.         MODIFY gt_data FROM gs_data INDEX sy-tabix.       ENDIF.     ENDLOOP.     " --- CHECK2 互斥     CLEAR lv_index.     LOOP AT gt_data INTO gs_data.       IF gs_data-check2 = 'X' AND lv_index IS INITIAL.         lv_index = sy-tabix.       ELSEIF gs_data-check2 = 'X' AND NOT lv_index IS INITIAL.         gs_data-check2 = space.         MODIFY gt_data FROM gs_data INDEX sy-tabix.       ENDIF.     ENDLOOP.     " --- 同列不能雙選     LOOP AT gt_data INTO gs_data.       IF gs_data-check1 = 'X' AND gs_data-check2 = 'X'.         " 清掉另一個         gs_data-check2 = space.         MODIFY gt_data FROM gs_data INDEX sy-tabix.       ENDIF.     ENDLOOP.     rs_selfield-refresh = 'X'.   ENDIF. ENDFORM. *--------------------------------------------------------------------- * 8. 主程式 *--------------------------------------------------------------------- START-OF-SELECTION.   PERFORM get_data_from_zvbank.   PERFORM build_fieldcat.   PERFORM set_layout.   data : gd_repid like sy-repid. gd_repid = sy-repid.   CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'     EXPORTING       i_callback_program       = gd_repid       i_callback_user_command  = 'USER_COMMAND'       i_callback_pf_status_set = 'FRM_SET_STATUS'       is_layout_lvc            = gs_layout       it_fieldcat_lvc          = gt_fieldcat       it_drop_down_list        = gt_dropdown     TABLES       t_outtab                 = gt_data. if sy-subrc <&gt; 0.   message id sy-msgid type sy-msgty number sy-msgno           with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. endif. *&---------------------------------------------------------------------* *&       Form  frm_set_status *&---------------------------------------------------------------------* form frm_set_status using rt_extab type slis_t_extab.   clear: rt_extab.   refresh: rt_extab.   set pf-status 'ALV_STATUS'. endform.
最新发布
08-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值