除了C ++中与内存分配相关的内容之外,还需要void*
吗?
你能举个例子吗?
答案 0 :(得分:5)
如果你想使用iostream输出一个指针(例如用于记录),那么通过void*
进行是确保operator<<
没有以某种疯狂方式过载的唯一方法。
#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;
}
iostreams重载operator void*
作为状态检查,因此像if (stream)
或while (stream)
这样的语法是测试流状态的简便方法。
您可能希望将void*
模板元编程有时用作减少捕获全部,例如使用SFINAE技巧,但通常使用某种形式的部分特化可以更好地解决它。
正如Alf在评论dynamic_cast<void*>
中指出的那样,对于获取层次结构中最派生的类型也是有用的,例如:
#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);
}
给出:
foo
0xbfb815f8
0xbfb815f8
bar
0xbfb815e4
0xbfb815e4
bar
0xbfb815ec
0xbfb815e4
在我的系统上。
§15.3.1陈述:
异常声明不应表示指针或引用 不完整的类型,除了void *,
const void*
,volatile void *或者 const volatile void *。
因此,似乎是通过void*
捕获指向不完整类型的指针的唯一合法方式。 (虽然我认为如果你真的需要使用它可能会有更大的问题)
void*
有很多“遗留”C用于存储指向数据的指针而不知道它是什么,但在新的C ++代码中,几乎总有一种表达相同功能的更好方法。
答案 1 :(得分:2)
外部库经常使用它们(特别是在C中)。
在这种情况下,我通常会隐藏这些库的使用(或更危险的部分)。我通过在它们周围编写接口来隐藏它们(比如包装)。我写的接口用于将类型安全引入程序。在这种情况下,void*
可能是必需的,但至少它是隐藏的并且仅限于方法或回调。
答案 2 :(得分:2)
答案 3 :(得分:1)
不,不是。引用非类型内存
只是一个成语答案 4 :(得分:1)
您可能想要使用void的一种情况是在传递数据缓冲区时,例如在此函数中:
void loadData(void* data, std::size_t size)
许多代码通过char-pointer而不是void-pointer传递缓冲区,因为通常情况下,缓冲区以1字节块的形式读取,这恰好是C ++标准确保char
为有
但是,使用void-pointers更通用。这是函数告诉你的一种方式,“只要给我一些数据,不要担心我会如何阅读它”。然后,该函数可以转换指针并以块或其喜欢的大小读取数据。
答案 5 :(得分:1)
void *在C ++中用于表示未知结构的指针类型。
所以每当我有一个指针类型时我会使用它,代码不应该知道那里有什么:
通常无效*与模板代码混合得很好,以避免模板引起的代码膨胀。
想象一下你实现了
template <typename T>
class vector {
/*stuff */
};
然后,您可以为T *创建一个模板特化,它使用void指针,因此代码不会重复。