other languages
other sections
Tcl_Obj(3tcl) | Tcl Library Procedures | Tcl_Obj(3tcl) |
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)
- 指向一個對象;必須是以前調用
Tcl_NewObj 返回的結果。
介紹 INTRODUCTION¶
這個手冊頁提供了對 Tcl 對象以及如何使用它們的一個概述。它還描述了管理 Tcl 對象的一些一般過程。使用這些過程來建立和複製對象,和增加和減少到對象的引用(指針)計數。這些過程與那些在特定類型的對象如 Tcl_GetIntFromObj 和 Tcl_ListObjAppendElement 上進行操作的過程聯合使用。單獨的過程和它們所操縱的數據結構被放在一起描述。 Tcl 的雙端口( dual-ported)對象為存儲和交換 Tcl 值提供了一個通用的機制。它們在很大程度上替代了 Tcl 中字符串的使用。例如,它們被用來存儲變量值、命令參數、命令結果、和稿本。Tcl 對象外在表現很像字符串,但它還持有可以被更加有效的操縱的內部表示。例如,現在一個 Tcl 列表被表示為持有列表的字符串表示的一個對象,如同到每個列表元素的指針的一個數組。雙端口對象避免了運行時的類型轉換。它們還提高了許多操作的速度,原因是可以立即獲得一個適當的表示。編譯器自身使用 Tcl 對象來緩存(cache)作為編譯稿本的結果的字節碼指令。 這兩種表示互為緩存並且被以懶惰方式計算。就是說,每個表示都只在需要時才被計算,它被從另一種表示計算出來,而一旦被計算出來了,它就被保存起來。除此之外,其中一個表示的改變將使另一個表示成為無效 。舉個例子,一個做整數運算的 Tcl 程式可以在一個變量的內部機器整數表示上進行直接操作,而不需要經常性的在整數和字符串之間進行轉換。只有在需要這個變量的值的一個字符串表示的時候,比如列印它,程式才重新生成這個整數的字符串表示。儘管對象包含一個內部表示,但它們的語義仍是依據字符串定義的: 總是可以獲取最新的字符串,在取回對象的字符串表示的時候,對對象的任何改變都將反映到取回的那個字符串上。因為這個表示是無效的並被重新生成了,擴展作者直接訪問 Tcl_Obj 的字段是很危險的。最好使用 Tcl_GetStringFromObj 和 Tcl_GetString 這樣的過程來訪問 Tcl_Obj 信息。 在堆上分配對象,使用到它們的 Tcl_Obj 結構的指針引用對象。對象要盡可能的共享。這將顯著的縮減存儲需求,原因是一些對象比如長列表是非常大的。還有,多數 Tcl 值只是被讀而從不被修改。尤其是過程參數,它們可以在調用和被調用的過程之間共享。賦值和參數綁定是通過簡單的賦予到這個值的一個指針完成的。使用引用計數來確定什麼時候歸還一個對象的存儲是安全的。 Tcl 對象是有類型的(typed)。一個對象的內部表示由它自己的類型來控制。在 Tcl 核心中預定義了七種類型,其中包括:整數、雙精度浮點數、列表、和字節碼。擴展作者可是使用 Tcl_RegisterObjType 過程來擴展類型的集合。對象結構 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;
對象生命周期示例 EXAMPLE OF THE LIFETIME OF AN OBJECT¶
作為一個對象生命周期的一個例子,考慮下列命令序列:set x 123
puts "x is $x"
incr x
puts "x is now $x"
對象的存儲管理 STORAGE MANAGEMENT OF OBJECTS¶
Tcl 對象在堆上分配,並且要盡可能的共享對象來縮減存儲需求。使用引用計數來確定何時一個對象不再被需要並可以被安全的釋放。剛用 Tcl_NewObj 或 Tcl_NewStringObj 建立的對象的 refCount 是 0。當建立到這個對象的一個新引用時,使用宏 Tcl_IncrRefCount 增加引用計數。當不再需要一個引用的時候 ,使用 Tcl_DecrRefCount 減少引用計數,而且如果這個對象的引用計數下降到零,就釋放它的存儲。被不同的代碼或數據結構共享的一個對象的 refCount 大於 1。增加一個對象的引用計數來確保它不會被過早釋放或者它的值被意外的改變。 舉個例子,字節碼解釋器在調用者和被調用的過程之間共享參數對象,以避免複製對象。它把調用者的實際參數的對象賦值給過程的形式參數變量。此時,它調用 Tcl_IncrRefCount 來增加每個實際參數(所引用的)的對象的引用計數,原因是有了從形式參數到這個對象的一個新引用。在被調用的過程返回的時候,解釋器調用 Tcl_DecrRefCount 來減少每個參數的引用計數。當一個對象的引用下降到小於等於零的時候, Tcl_DecrRefCount 歸還它的存儲。多數命令過程不是必須關心引用計數的,原因是它們立即使用一個對象的值並且在它們返回之後不保留到這個對象的指針。但是,如果它們把到一個對象的指針保留到一個數據結構中,則他們必須注意要增加它的引用計數,原因是這個保留的指針是一個新引用。 像 lappend 和 linsert 這樣的直接修改對象的命令過程必須注意要在修改一個共享的對象之前複製它。 他們必須首先調用 Tcl_IsShared 來檢查這個對象是否是共享的。如果對象是共享的,則他們必須使用 Tcl_DuplicateObj 複製這個對象;它返回原始對象的一個新複製品,其 refCount 是 0。如果對象未被共享,則命令過程「擁有」這個對象並可以安全的直接修改它。例如,下列代碼出現在實現 linsert 的命令過程當中。通過在 index 的前面插入 objc-3 新元素,這個過程修改在 objv[1] 中傳遞給它的列表對象 。listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { listPtr = Tcl_DuplicateObj(listPtr); } result = Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]));
參見 SEE ALSO¶
Tcl_ConvertToType, Tcl_GetIntFromObj, Tcl_ListObjAppendElement, Tcl_ListObjIndex, Tcl_ListObjReplace, Tcl_RegisterObjType關鍵字 KEYWORDS¶
internal representation, object, object creation, object type, reference counting, string representation, type conversion[中文版維護人]¶
寒蟬退士[中文版最新更新]¶
2001/10/30《中國 Linux 論壇 man 手冊頁翻譯計劃》:¶
http://cmpp.linuxforum.net8.0 | Tcl |