Provided by: manpages-zh_1.5.1-1_all bug

NAME

       Tcl_NewObj,   Tcl_DuplicateObj,   Tcl_IncrRefCount,   Tcl_DecrRefCount,
       Tcl_IsShared, Tcl_InvalidateStringRep - 操縱 Tcl 對象

` SYNOPSIS
       #include <tcl.h>

       Tcl_Obj *
       Tcl_NewObj()

       Tcl_Obj *
       Tcl_DuplicateObj(objPtr)

       Tcl_IncrRefCount(objPtr)

       Tcl_DecrRefCount(objPtr)

       int
       Tcl_IsShared(objPtr)

       Tcl_InvalidateStringRep(objPtr)

 ARGUMENTS
       Tcl_Obj   *objPtr   (in)      指向一蚢龠H;必須是以前調用    Tcl_NewObj
                                     返回的結果。
_________________________________________________________________

 INTRODUCTION
       這茪漭U韌ㄗ悀F對   Tcl  對象以及如何使用它怐漱@虓囫。它還描z了管理  Tcl
       對象的一些一般過程。使用這些過程來建立和複製對象,和增加和減少到對象的引用(指針)-
       p數。這些過程與那些在特定類型的對象如        Tcl_GetIntFromObjTcl_ListObjAppendElement      上進行操作的過程聯合使用。單獨的過程和它-
       怍瓴瓾a的數據結構被放在一起描z。

       Tcl 的雙端口(dual-ported)對象為存儲和交換 Tcl ㄗ悀F一茬q用的機制。它-
       怞b很大程度上替代了    Tcl     中字符串的使用。例如,它抭Q用來存儲變量-
       B命令參數、命令結果、和稿本。Tcl
       對象外在表現很像字符串,但它還持有可以被更加有效的操縱的內部表示。例如,現在一-
               Tcl       列表被表示為持有列表的字符串表示的一蚢龠H,如同到每-
       茼C表元素的指針的一蚍捸C雙端口對象避免了運行時的類型轉換。它-
       攽棷ㄟ炊F釵h操作的速度,鴞]是可以立即獲得一蚞A當的表示。編譯器自豕洏
       Tcl 對象來緩存(cache)作為編譯稿本的結果的字節碼指令。

       這兩種表示互為緩存並且被以懶惰方式p算。就是說,每茠磳亶ㄔu在需n時才被-
       p算,它被從另一種表示p算出來,而一旦被-
       p算出來了,它就被保存起來。除此之外,其中一茠磳靰漣幭亃N使另一-
       茠磳雃足做L效      。舉茖狺l,一荌翔蒱B算的     Tcl     程式可以在一-
       蚥僆q的內部機器整數表示上進行直接操作,而不需-
       n經常性的在整數和字符串之間進行轉換。只有在需n這蚥僆q的漱@-
       茼r符串表示的時唌A比如列印它,程式才奐s生成這-
       蚞蒱漲r符串表示。儘管對象包含一茪熙〞磳隉A但它-
       怐獄y義仍是依據字符串定義的:
       總是可以獲取最新的字符串,在取回對象的字符串表示的時-
       唌A對對象的任何改變都將反映到取回的那茼r符串上。因為這-
       茠磳頇O無效的並被奐s生成了,擴展作者直接訪問                    Tcl_Obj
       的字段是很危險的。最好使用   Tcl_GetStringFromObjTcl_GetString
       這樣的過程來訪問 Tcl_Obj 信息。

       在堆上分配對象,使用到它怐      Tcl_Obj      結構的指針引用對象。對象-
       n盡可能的共享。這將顯著的縮減存儲需求,-
       鴞]是一些對象比如長列表是非常大的。還有,多數   Tcl  u是被讀而從不被-
       蚹鵅C尤其是過程參數,它怚i以在調用和被調用的過程之間共享。賦-
       M參數綁定是通過簡單的賦予到這蚧的一茷針完成的。使用引用-
       p數來確定什麼時堎k還一蚢龠H的存儲是安全的。

       Tcl    對象是有類型的(typed)。一蚢龠H的內部表示由它自己的類型來控制。在
       Tcl
       核心中預定義了七種類型,其中包括:整數、雙精度浮點數、列表、和字節碼。擴展作者可是使用
       Tcl_RegisterObjType  過程來擴展類型的集合。

Hc THE TCL_OBJ STRUCTURE
       每 Tcl 對象都被表示為一 Tcl_Obj 結構,其定義如下。
              typedef struct Tcl_Obj {
                int refCount;
                char *bytes;
                int length;
                Tcl_ObjType *typePtr;
                union {
                   long longValue;
                   double doubleValue;
                   VOID *otherValuePtr;
                   struct {
                     VOID *ptr1;
                     VOID *ptr2;
                   } twoPtrValue;
                } internalRep;
              } Tcl_Obj;
       byteslength    成一起持有一蚢龠H的字符串表示,這是一茪wp數的
       (counted)  字符串或二進制串  (binary  string),二進制串可能包含有嵌入的
       null   字節的二進制串。bytes  指向這茼r符串表示的第一茼r節。length  成-
       給出字節數。字節數組的在偏移量     length     上,也就是最後一茼r節後-
       悼眸溥`是有一   null;這允酗ㄔ]含  null  的字符串表示被作為一荓`規的用
       null 終結的 C 語言字符串來對待。  C  程式使用  Tcl_GetStringFromObjTcl_GetString       來得到一蚢龠H的字符串表示。如果       bytes      是
       NULL,則字符串表示無效。

       一蚢龠H的類型管理它的內部表示。成  typePtr  指向描z類型的  Tcl_ObjType
       結構。如果 typePtr is 是 NULL,則內部表示無效。

       internalRep      聯合成持有一蚢龠H的內部表示。它可以是一(長)整數,一-
       蚋戇諞蚽B點數,或者一茷針、它指向包含這蚚型的對象n表示對象所需-
       n的補充信息的A或者是兩茈艩N的指針。

       使用  refCount 成來通告在什麼時堐孺韙@蚢龠H的存儲是安全的。它持有到這-
       蚢龠H的活躍引用的p數。維護正確的引用p數是擴展作者的一-
       蚚鶬銎坁熙d任。在下悸犒龠H的存儲管理  (STORAGE  MANAGEMENT  OF OBJECTS)
       章節中討論了引用p數。

       儘管擴展的作者可以直接訪問一             Tcl_Obj             結構的成-
       ,但最好還是使用恰當的過程和宏。例如,擴展作者永遠不n直接讀或蚹
       refCount;作為替代,他抸雪磻洏庣  Tcl_IncrRefCountTcl_IsShared
       這樣的宏。

       Tcl    對象的一蚚鶬鞂搣坌O它持有兩茠磳隉C典型的,一蚢龠H開始時只包含一-
       茼r符串表示: 它是無類型的並且typePtr 是一 NULL。分別使用 Tcl_NewObjTcl_NewStringObj  建立包含一茠臟磢漱@蚢龠H或一茷定字符串的一荋_件。一-
       蚢龠H的字符串i以使用    Tcl_GetStringFromObjTcl_GetString
       來獲取並使用  Tcl_SetStringObj  來改變它。如果如果這蚢龠H以後被傳遞給像
       Tcl_GetIntFromObj  這樣的n求一荅S定的內部表示的過程,則這蚢L程將建立一-
       茪熙〞磳雰籀]置這蚢龠H的    typePtr。從字符串表示來p算它的內部表示。一-
       蚢龠H的兩茠磳頇O雙囿:                       對一茠漣幭雂]將反映到另一-
       茪W。例如,Tcl_ListObjReplace           將蚹鴾@蚢龠H的內部表示,下一茖
       Tcl_GetStringFromObjTcl_GetString 的調用將反映這荍幭隉C

       出於效率的鴞]以懶惰方式厚算表示。一蚢L程如   Tcl_ListObjReplace   對一-
       茠磳靰漣幭雂ㄔ艂Y反映到另一茠磳雂W。作為替代,把另一-
       茠磳僂訄O為無效,如果以後需n的話再奐s生成。多數         C         程式-
       永遠無須關心這是如何完成的,他怚u是簡單的使用像  Tcl_GetBooleanFromObjTcl_ListObjIndex       這樣的過程。而實現自己的對象類型的程式-
       必須檢查無效表示和在需n時標記一茠磳頇做L效。使用過程
       Tcl_InvalidateStringRep      來標記一蚢龠H的字符串表示為無效並釋放與這-
       茼r符串表示相關聯的存儲。

       對象在它的一生當中通常保持一種類型,但是有時一-
       蚢龠H必須從一種類型轉換成另一種類型。例如,一  C   程式可以通過契_調用
       Tcl_AppendToObj 來在一蚢龠H中建造一茼r符串,並接著調用 Tcl_ListObjIndex
       來從一蚢龠H中提取一茼C表元素。持有相同字符串的同樣的對象在不同的時-
       唹i能有多種不同的內部表示。擴展作者可以使用           Tcl_ConvertToType
       過程強制把一蚢龠H從一種類型轉換成另一種類型。只有建立新對象類型的程式-
       才需n關心這是如何作的。作為對象類型實現的一部分,需n定義為一-
       蚢龠H建立一虓s的內部表示和改變它     typePtr     的一蚢L程。如何建立一-
       虓s對象類型請參見 Tcl_RegisterObjType 手冊間C

HRP EXAMPLE OF THE LIFETIME OF AN OBJECT
       作為一蚢龠H生命周期的一茖狺l,考慮下列命令序列:
              set x 123
       這裏把一茈憚壅型的對象賦  x,這蚢龠H的  bytes 成指向 123length
       成包含 3。對象的 typePtr 成是 NULL。
              puts "x is $x"
       x 的字符表示是有效的(因為 bytes 是非 NULL)並被這茤R令取回。
              incr x
       incr 命令漸通過調用 Tcl_GetIntFromObj 從  x  (所引用的)的對象的得到一-
       蚞蒱C這蚢L程檢查這蚢龠H是否已經是一蚞蒱龠H。由於它不是,就通過把這-
       蚢龠H的 internalRep.longValue 成設置為整數 123,並把這蚢龠H的  typePtr
       設置為指向整數的 Tcl_ObjType 結構,此過程把這蚢龠H轉換成了整數對象。兩-
       茠磳亄{在都是有效的。incr                                       增加這-
       蚢龠H的整數內部表示,接著使它的字符串表示無效(通過調用
       Tcl_InvalidateStringRep),鴞]是這茼r符串表示不再與內部表示相對應了。
              puts "x is now $x"
       現在需n   x   (所引用的)的對象的字符串表示,n奐sp算它。字符串表示現在是
       124。兩茠磳雂S都是有效的了。

Hsxz STORAGE MANAGEMENT OF OBJECTS
       Tcl      對象在堆上分配,並且n盡可能的共享對象來縮減存儲需求。使用引用-
       p數來確定何時一蚢龠H不再被需n並可以被安全的釋放。镼    Tcl_NewObjTcl_NewStringObj   建立的對象的   refCount  是  0。當建立到這蚢龠H的一-
       虓s引用時,使用宏  Tcl_IncrRefCount  增加引用p數。當不再需n一茪犍峈漁尕
       ,使用     Tcl_DecrRefCount    減少引用p數,而且如果這蚢龠H的引用p數下-
       馬儦s,就釋放它的存儲。被不同的代碼或數據結構共享的一蚢龠H的   refCount
       大於              1。增加一蚢龠H的引用p數來確保它不會被過汛孺顑峈怚扛-
       Q意外的改變。

       舉-
       茖狺l,字節碼解釋器在調用者和被調用的過程之間共享參數對象,以避免複製對象。它把調用者的實際參數的對象賦-
       凳L程的形式參數變量。此時,它調用     Tcl_IncrRefCount      來增加每-
       蚢篕痚捊(所引用的)的對象的引用p數,鴞]是有了從形式參數到這蚢龠H的一-
       虓s引用。在被調用的過程返回的時唌A解釋器調用 Tcl_DecrRefCount 來減少每-
       荌捊漱犍姩數。當一蚢龠H的引用下馬鴗p於等於零的時唌A  Tcl_DecrRefCount
       歸還它的存儲。多數命令過程不是必須關心引用p數的,鴞]是它怚艂Y使用一-
       蚢龠H的疇B在它怐藀^之後不保留到這蚢龠H的指針。但是,如果它怬漼鴗@-
       蚢龠H的指針保留到一蚍痤硎c中,則他怚眸楫`意n增加它的引用p數,鴞]是這-
       茷O留的指針是一虓s引用。

       像   lappendlinsert  這樣的直接蚹儮龠H的命令過程必須注意n在蚹鴾@-
       茼@享的對象之前複製它。    他怚眸滓先調用    Tcl_IsShared     來檢查這-
       蚢龠H是否是共享的。如果對象是共享的,則他怚眸楊洏     Tcl_DuplicateObj
       複製這蚢龠H;它返回鴝l對象的一虓s複製品,其         refCount         是
       0。如果對象未被共享,則命令過程「擁有」這蚢龠H並可以安全的直接-
       蚹鴷式C例如,下列代碼出現在實現 linsert  的命令過程當中。通過在   index
       的前探﹞J objc-3 新元素,這蚢L程蚹鵀b objv[1] 中傳遞給它的列表對象 。

              listPtr = objv[1];
              if (Tcl_IsShared(listPtr)) {
                listPtr = Tcl_DuplicateObj(listPtr);
              }
              result = Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]));

       另一茖狺l,incr
       的命令過程在增加變量(所引用的)對象內部表示中的整數之前,必須檢查這-
       蚥僆q(所引用的)對象是否是共享的。如果它是共享的,則需n複製這-
       蚢龠H,目的是避免意外的改變在其他數據結構中C

 SEE ALSO
       Tcl_ConvertToType,     Tcl_GetIntFromObj,     Tcl_ListObjAppendElement,
       Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_RegisterObjType

r KEYWORDS
       internal   representation,   object,   object  creation,  object  type,
       reference counting, string representation, type conversion

[]
      Hhh

[]
       2001/10/30

m Linux manUpn:
       http://cmpp.linuxforum.net