问题
Is void*
necessary apart from memory allocation related stuff in C++?
Can you give me an example?
回答1:
Logging memory addresses
If you want to output a pointer using iostreams (e.g. for logging) then going via void*
is the only way of ensuring operator<<
hasn't been overloaded in some crazy way.
#include <iostream>
struct foo {
};
std::ostream& operator<<(std::ostream& out, foo*) {
return out<<"it's a trap!";
}
int main() {
foo bar;
foo *ptr = &bar;
std::cout << ptr << std::endl;
std::cout << static_cast<void*>(ptr) << std::endl;
}
Testing iostream status
iostreams overload operator void*
as a status check so that syntax like if (stream)
or while (stream)
is a short hand way of testing the stream status.
Template meta programming
You might want to use void*
with template metaprogramming sometimes as a reduced catch all, e.g. with SFINAE tricks, but more often than not there's a nicer way around it using a partial specialisation of one form or another.
Accessing most derived pointer
As Alf pointed out in the comments dynamic_cast<void*>
is also useful for getting at the most derived type in a heirarchy, e.g.:
#include <iostream>
struct other {
virtual void func() = 0;
int c;
};
struct foo {
virtual void func() { std::cout << "foo" << std::endl; }
int a;
};
struct bar : foo, other {
virtual void func() { std::cout << "bar" << std::endl; }
int b;
};
namespace {
void f(foo *ptr) {
ptr->func();
std::cout << ptr << std::endl;
std::cout << dynamic_cast<void*>(ptr) << std::endl;
}
void g(other *ptr) {
ptr->func();
std::cout << ptr << std::endl;
std::cout << dynamic_cast<void*>(ptr) << std::endl;
}
}
int main() {
foo a;
bar b;
f(&a);
f(&b);
g(&b);
}
Gives:
foo
0xbfb815f8
0xbfb815f8
bar
0xbfb815e4
0xbfb815e4
bar
0xbfb815ec
0xbfb815e4
On my system.
Exceptions
§ 15.3.1 states:
The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void*,
const void*
, volatile void*, or const volatile void*.
So it seems to be the only legal way of catching a pointer to an incomplete type is via void*
. (Although I think there's possibly bigger issues if you actually needed to use that)
Legacy C uses
There are a lot of "legacy" C uses for void*
for storing pointers to data without knowing what it is, but in new C++ code there is almost always a better way of expressing the same functionality.
回答2:
external libraries use them often (esp. in C).
in this case, i'll usually hide the use of these libraries (or the more dangerous portions). i hide them by writing interfaces around them (like wrapping). the interfaces i write serve to introduce type safety into the program. in this case, void*
may be required, but at least it's hidden and restricted to a method or callback.
回答3:
void*
is frequently used for callbacks.
Callbacks are generally implemented in the C language using function pointers and auxiliary user-defined data passed as a void pointer for genericity.
[from here]
Of course, this is not type-safe, so people come up with ways to wrap this kind of thing, like here.
回答4:
No it isn't. It's only an idiom to refer to non typed memory
回答5:
One situation where you might want to use void is when passing around data buffers, such as in this function:
void loadData(void* data, std::size_t size)
A lot of code passes buffers through a char-pointer instead of a void-pointer because, typically, buffers are read in 1 byte chunks, which happens to be the size that the C++ standard ensures a char
to have.
However, using void-pointers is more generic. It's a way for the function to tell you, "Just give me some data, don't worry about how I'll read it". The function can then cast the pointer and read the data in chunks or whatever size it likes.
回答6:
void * is used in C++ to express a pointer type to an unknown structure.
So I would use it whenever I have a pointer type where the code shouldn't know what is in there:
- memory allocation
- containers
- ...
Often void * mix quite well with template code to avoid template induced code bloat.
imagine you implement a
template <typename T>
class vector {
/*stuff */
};
you can then create a template specialisation for T * which uses void pointers so the code doesn't get duplicated.
来源:https://stackoverflow.com/questions/7298872/is-void-necessary-apart-from-memory-allocation-related-stuff