Standard C++ supports pointer types and null pointer constants. C++/CLI adds handle types and null values. 20To help integrate handles, and to have a universal null, C++/CLI defines the keyword nullptr. This 21keyword represents a literal having the null type. nullptr is referred to as the null value constant. (No 22instances of the null type can ever be created, and the only way to obtain a null value constant is via this 23keyword.) 24The definition of null pointer constant (which Standard C++ requires to be a compile-time expression that 25evaluates to zero) has been extended to include nullptr. The null value constant can be implicitly 26converted to any pointer or handle type, in which case it becomes a null pointer value or null value, 27respectively. This allows nullptr to be used in relational, equality, conditional, and assignment 28expressions, among others. 29Object^ obj1 = nullptr; // handle obj1 has the null value 30String^ str1 = nullptr; // handle str1 has the null value 31if (obj1 == 0); // false (zero is boxed and the two handles 32differ) 33if (obj1 == 0L); // false “ “ “ “ “ 34if (obj1 == nullptr); // true 35char* pc1 = nullptr; // pc1 is the null pointer value 36if (pc1 == 0); // true as zero is a null pointer value 37if (pc1 == 0L); // true “ “ “ 38if (pc1 == nullptr); // true as nullptr is a null pointer constant 39int n1 = 0; 40n1 = nullptr; // error, no implicit conversion to int 41if (n1 == 0); // true, performs integer comparison 42if (n1 == 0L); // “ “ “ 43if (n1 == nullptr); // error, no implicit conversion to int 44if (nullptr); // error 45if (nullptr == 0); // error, no implicit conversion to int 46if (nullptr == 0L); // “ “ “ 47nullptr = 0; // error, nullptr is not an lvalue 48nullptr + 2; // error, nullptr can’t take part in arithmetic 49Object^ obj2 = 0; // obj2 is a handle to a boxed zero 50Object^ obj3 = 0L; // obj3 “ “ “ 51String^ str2 = 0; // error, no conversion from int to String^ 52String^ str3 = 0L; // “ “ “ “ 53char* pc2 = 0; // pc2 is the null pointer value 54char* pc3 = 0L; // pc3 “ “ “ 55Language overview15Object^ obj4 = expr ? nullptr : nullptr; // obj4 is the null value 1Object^ obj5 = expr ? 0 : nullptr; // error, no composite type 2char* pc4 = expr ? nullptr : nullptr; // pc4 is the null pointer 3value 4char* pc5 = expr ? 0 : nullptr; // error, no composite type 56int n2 = expr ? nullptr : nullptr; // error, no implicit conversion to 7int 8int n3 = expr ? 0 : nullptr; // error, no composite type 9sizeof(nullptr); // error, the null type has no size, per se 10typeid(nullptr); // error 11throw nullptr; // error 12void f(Object^); // 1 13void f(String^); // 2 14void f(char*); // 3 15void f(int); // 4 16f(nullptr); // error, ambiguous (1, 2, 3 possible) 17f(0); // calls f(int) 18void g(Object^, Object^); // 1 19void g(Object^, char*); // 2 20void g(Object^, int); // 3 21g(nullptr, nullptr); // error, ambiguous (1, 2 possible) 22g(nullptr, 0); // calls g(Object^, int) 23g(0, nullptr); // error, ambiguous (1, 2 possible) 24void h(Object^, int); 25void h(char*, Object^); 26h(nullptr, nullptr); // calls h(char*, Object^); 27h(nullptr, 2); // calls h(Object^, int); 28template<typename T> void k(T t); 29k(0); // specializes k, T = int 30k(nullptr); // error, can’t instantiate null type 31k((Object^)nullptr); // specializes k, T = Object^ 32k<int*>(nullptr); // specializes k, T = int* 33Since objects allocated on the native heap do not move, pointers and references to such objects need not 34track an object’s location. However, objects on the CLI heap can move, so they require tracking. As such, 35native pointers and references are not sufficient for dealing with them. To track objects on the CLI heap, 36C++/CLI defines handles (using the punctuator ^) and tracking references (using the punctuator %). 37N* hn = new N; // allocate on native heap 38N& rn = *hn; // bind ordinary reference to native object 39R^ hr = gcnew R; // allocate on CLI heap 40R% rr = *hr; // bind tracking reference to gc-lvalue 41In general, the punctuator % is to ^ as the punctuator & is to *. 42Just as Standard C++ has a unary & operator, C++/CLI provides a unary % operator. While &t yields a T* or 43an interior_ptr<T> (see below), %t yields a T^. 44Rvalues and lvalues continue to have the same meaning as with Standard C++, with the following rules 45applying: 46• An entity declared with type T*, a native pointer to T, points to an lvalue. 47• Applying unary * to an entity declared with type T*, dereferencing a T*, yields an lvalue. 48• An entity declared with type T&, a native reference to T, is an lvalue. 49• The expression &lvalue yields a T*. 50• The expression %lvalue yields a T^. 51A gc-lvalue is an expression that refers to an object that might be on the CLI heap, or to a value member 52contained within such an object. The following rules apply to gc-lvalues: 53C++/CLI Language Specification16• Standard conversions exist from “cv-qualified lvalue of type T” to “cv-qualified gc-lvalue of 1type T,” and from “cv-qualified gc-lvalue of type T” to “cv-qualified rvalue of type T.” 2• An entity declared with type T^, a handle to T, points to a gc-lvalue. 3• Applying unary * to an entity declared with type T^, dereferencing a T^, yields a gc-lvalue. 4• An entity declared with type T%, a tracking reference to T, is a gc-lvalue. 5• The expression &gc-lvalue yields an interior_ptr<T> (see below). 6• The expression %gc-lvalue yields a T^. 7The garbage collector is permitted to move objects that reside on the CLI heap. In order for a pointer to refer 8correctly to such an object, the runtime needs to update that pointer to the object’s new location. An interior 9pointer (which is defined using interior_ptr) is a pointer that is updated in this manner.

评论