转自:http://www.learncpp.com/cpp-tutorial/613-void-pointers/
简单说就是,void* 可以指向任何地址,但是在使用时不允许直接引用,而应该转成相应的类型才可以。即void * p = &addr; 正确,但是 cout<<*p <<endl; 是非法的。
另外,原文也总结了null point 与 void point的区别,简单说就是null point不指向任何地址,而且voidpoint可以指向任何地址,只不过不知道 它的具体类型而已。所以void point也可以是null point。
原文
The void pointer, also known as thegeneric pointer, is a special type of pointer that can be pointed at objects ofany data type! A void pointer is declared like a normal pointer, using the voidkeyword as the pointer’s type:
1 | void *ptr; // ptr is a void pointer |
A void pointer can pointto objects of any data type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | int nValue; float fValue;
struct Something { int n; float f; };
Something sValue;
void *ptr; ptr = &nValue; // valid ptr = &fValue; // valid ptr = &sValue; // valid |
However, because the voidpointer does not know what type of object it is pointing to, it cannot be dereferenceddirectly! Rather, the void pointer must first be explicitly cast to anotherpointer type before it is dereferenced.
1 2 3 4 5 6 7 8 | int value = 5; void *voidPtr = &value;
//cout << *voidPtr << endl; // illegal: cannot dereference a void pointer
int *intPtr = static_cast<int*>(voidPtr); // however, if we cast our void pointer to an int pointer...
cout << *intPtr << endl; // then we can dereference it like normal |
This prints:
5
The next obvious questionsis: If a void pointer doesn’t know what it’s pointing to, how do we know whatto cast it to? Ultimately, that is up to you to keep track of.
Here’s an example of avoid pointer in use:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <iostream>
enum Type { INT, FLOAT, CSTRING };
void printValue(void *ptr, Type type) { switch (type) { case INT: std::cout << *static_cast<int*>(ptr) << '\n'; // cast to int pointer and dereference break; case FLOAT: std::cout << *static_cast<float*>(ptr) << '\n'; // cast to float pointer and dereference break; case CSTRING: std::cout << static_cast<char*>(ptr) << '\n'; // cast to char pointer and dereference break; } }
int main() { int nValue = 5; float fValue = 7.5; char szValue[] = "Mollie";
printValue(&nValue, INT); printValue(&fValue, FLOAT); printValue(szValue, CSTRING);
return 0; } |
This program prints:
5
7.5
Mollie
Void pointer miscellany
Void pointers can be setto a null value:
1 | void *ptr = 0; // ptr is a void pointer that is currently a null pointer |
Although some compilersallow deleting a void pointer that points to dynamically allocated memory,doing so should be avoided, as it can result in undefined behavior.
It is not possible to dopointer arithmetic on a void pointer. This is because pointer arithmeticrequires the pointer to know what size object it is pointing to, so it canincrement or decrement the pointer appropriately.
Note that there is no suchthing as a void reference. This is because a void reference would be of typevoid &, and would not know what type of value it referenced.
Conclusion
In general, it is a goodidea to avoid using void pointers unless absolutely necessary, as theyeffectively allow you to avoid type checking. This allows you to inadvertentlydo things that make no sense, and the compiler won’t complain about it. Forexample, the following would be valid:
1 2 | int nValue = 5; printValue(&nValue, CSTRING); |
But who knows what theresult would actually be!
Although the abovefunction seems like a neat way to make a single function handle multiple datatypes, C++ actually offers a much better way to do the same thing (via functionoverloading) that retains type checking to help prevent misuse. Many otherplaces where void pointers would once be used to handle multiple data types arenow better done using templates, which also offer strong type checking.
However, veryoccasionally, you may still find a reasonable use for the void pointer. Justmake sure there isn’t a better (safer) way to do the same thing using otherlanguage mechanisms first!
Quiz
1) What’s the differencebetween a void pointer and a null pointer?
Quiz answers
1) Hide Solution
Avoid pointer is a pointer that can point to any type of object, but does notknow what type of object it points to. A void pointer must be explicitly cast intoanother type of pointer to be dereferenced. A null pointer is a pointer thatdoes not point to an address. A void pointer can be a null pointer.