C++/CLI中的const literal initonly 友元
Visual C++並不允許在const對象上調用成員函數,除非該成員函數也被聲明爲const。
C++/CLI託管代碼中,無法把任何類型的函數聲明爲const;但可以把一個對象聲明爲const;然而由於無法編寫const函數,這種const對象也幾乎沒有辦法進行操作。
我們可以在句柄和函數實參中使用const;就像對指針使用const一樣當;我們把一個引用傳遞給一個函數但有希望限制對這個引用所指向的數據進行修改時,這種做法很實用。
託管數組不支持const限定符,即無法在C++/CLI中使用const聲明或傳遞託管數組。
本地C++中的靜態常量成員在C++/CLI中應該只使用關鍵字literal聲明。被聲明爲literal的數據成員必須在聲明的時候進行初始化。literal必須是類的數據成員而不能是全局靜態變量。
C++/CLI使用inionly把一個成員變量聲明爲initonly指定了這個成員只能在類的構造函數中被賦值,但並不意味着它不可以被重新賦值,只是他無法在構造函數之外被賦值或重新賦值。
C++/CLI託管類無法聲明友元類或友元函數;本地類可以把託管類聲明爲它的友元。
堆棧語義
當我們在不使用new的情況下創建一個本地對象時,Visual C++把這種對象(自動變量)存儲在堆棧而不是本地堆中,堆棧內存是由C++運行時自動管理的。當自動變量離開作用域時,它的析構函數會被隱式的調用,它所佔據的內存會被自動收回,不需要程序員顯示的調用delete。這種風格的聲明稱爲堆棧語義。
C++/CLI並不允許我們對3種特定的託管類型使用堆棧語義:String對象,託管數組和委託。這些類型的對象必須被定義爲各自類型的句柄。任何其它C++/CLI類型以及任何自定義類型都可以使用堆棧語義來聲明。
託管代碼中的指針
interior_ptr<type>
是native pointer的超集,native pointer能做的,Interior pointer也一樣能做。當垃圾回收器移動對象時,Interior pointer能隨之移動,並始終指向該對象。
------《Pro Visual C++_CLI and the .NET 2.0 Platform》p815
Interior_ptr可以指向引用句柄、值類型、裝箱類型句柄、託管類成員、託管數組的元素。不能指向引用類型本身。
*ip 是ip所值的類型type的值
&ip 是ip指向託管堆中的地址
pin_ptr<type>
在外部調用託管堆中指針時,垃圾回收過程中該指針會發生改變,引起外部調用的錯誤。必須使用pin_ptr指針將該指針固定。
pinned pointer可以指向引用句柄、值類型、託管數組的元素。不能指向引用類型,但能指向引用類型的成員(不支持釘住由 new 表達式返回的整個對象。相反,需要釘住內部成員的地址。--MSDN)。可以完成native pointer的所有的功能,如指針比較和指針運算。
都不能由跟蹤句柄直接賦值。而是必須由&操作符取地址。因爲interior_ptr pin_ptr是獨立的類,只能由地址賦值,而不能由託管類型賦值。
int^ m_int = gcnew int(100);
interior_ptr<int> ipint = &*m_int; //ok
interior_ptr<int> ipint = m_int; //error
Value class Vtest{}Ref class Rtest{}Vtest ^vtest = gcnew Vtest; //值類型對象pin_ptr< Vtest > pinp;pinp = vtest; //errorpinp = &* vtest; //okinterior_ptr< Vtest > ip;ip = &* vtest; //okpin_ptr< Vtest ^> pinhundle;pinhundle = vtest; //errorpinhundle = & vtest; //okinterior_ptr< Vtest ^> iphundle;iphundle = & vtest; //okRTest ^rtest = gcnew RTest; //引用類型對象pin_ptr< Rtest > pinp; //error , 不可以釘住引用類型對象interior_ptr < Rtest > pinp; //error , 不可以指向引用類型對象ref class G {public: void incr(int* pi) { *pi += 1; }};ref struct H { int j; };void f( G^ g ) { H ^ph = gcnew H; Console::WriteLine(ph->j); pin_ptr<int> pj = &ph->j; //ok,可以釘住引用類型對象的成員 g->incr( pj ); Console::WriteLine(ph->j);}
Pin_ptr指針使用例子
value class Test {public: int i; };#pragma unmanagedvoid incr (int *i){ (*i) += 10;}#pragma managedvoid main () { Test ^test = gcnew Test(); interior_ptr<int> ip = &test->i; (*ip) = 5;// incr( ip ); // invalid pin_ptr<int> i = ip; // i is a pinned int pointer incr( i ); // pinned pointer to interior pointer passed to a // native function call expecting a native pointer Console::WriteLine ( test->i );}
非託管代碼中的函數void incr(int *i)需要int指針,不能將interior_ptr<int>的ip傳遞給該函數。因爲內部指針會隨着垃圾回收改變地址,而將其轉換爲pin_ptr<int>,就是將地址固定,以供外部函數incr(int* i)調用該指針。
和*指針的轉換
正因爲pin_ptr<>所指向的地址是固定的,因此才能和*指針轉換。而interior_ptr<>無此性質。
pin_ptr<ClassValue> pValue = &value;; ClassValue* p = pValue; //ok
interior_ptr就不可以和*指針轉換。
interior_ptr<ClassValue> pValue = &value;; ClassValue* p = pValue; //error
值類型的指針
在新語法中,值類型指針分爲兩種類型:V*(限於非 CLR 堆位置)和內部指針 interior_ptr<V>(允許但不要求託管堆內的地址)。
// may not address within managed heap
V *pv = 0;
// may or may not address within managed heap
interior_ptr<V> pvgc = nullptr;
託管擴展中的下列聲明全部映射到新語法中的內部指針。(它們是 System命名空間內的值類型。)
Int32 *pi; // => interior_ptr<Int32> pi;
Boolean *pb; // => interior_ptr<Boolean> pb;
E *pe; // => interior_ptr<E> pe; // Enumeration
內置類型不被認爲是託管類型,儘管它們確實在System命名空間內作爲類型的別名。
---------------------
作者:polinzhuo
來源:CSDN
原文:https://blog.csdn.net/polinzhuo/article/details/1527089
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!
Reference:C++/CLI 實戰技術收集