我在想,为什么不能有一个不是指针的void数据类型?
当然,你可以通过
来超越整个确定的大小void4
void8
void32
然后只允许将一个void数据类型“强制转换”为另一个类,如果它的大小等于或小于类的大小。
我有什么遗漏,或者C ++委员会是否认为这是不好的做法?
编辑:
我没有很好地解释自己,所以我将举例说明它的用法:
main()
{
/*
Lets make a list of unknown elements
std::string is 8 bytes, and float is 4
bytes, so we'll reserve 8 byte sequences
*/
vector<void8> elements;
elements.push_back((void8) string("First string element"));
elements.push_back((void8) float(5.76) );
elements.push_back((void8) string("Third string element"));
// Ect.
cout << (string) elements[0];
cout << (float) elements[1];
cout << (string) elements[2];
cout << (float) elements[2]; // Garbage
void1 data;
data = (void1) bool(1);
data = (void1) unsigned int(80094); // Error, not enough size
}
它的名为void,因为您不知道它当前存储的类型,类似于void指针。
答案 0 :(得分:8)
它被称为boost :: variant或boost :: any。它是允许的最大数据类型+ sizeof(指针)的大小,完全是类型安全的。
答案 1 :(得分:3)
在强类型语言中,所有数据都有一个类型,因此没有“void”概念作为数据类型。在C和C ++中,它的意思是“无数据”(作为返回值),或“你不知道的类型的数据”(作为指针目标)。
您提出的中间状态为“您不知道但其大小与您相同的数据”,可能是您通过值传递的类型的不透明版本。除了相当危险之外(因为你必须在更改真实类型的大小时使用opaque类型手动更新所有代码),这可以在不添加语言的奇怪扩展的情况下完成,例如:< / p>
struct void8 { char bytes[8]; };
这个可以与reinterpret_cast
一起使用,将POD类型作为不透明的块传递,就像你建议的那样。与非POD类型一起使用它比使用void*
引用非POD类型更有可能调用未定义的行为。
将opaque类型作为指针或对已声明但尚未定义的命名类型的引用处理,或者如果您需要值语义,则处理boost::any
之类的内容会更安全,更惯用。在C ++中很少需要使用“void”作为占位符类型。
答案 2 :(得分:2)
“void”数据类型的含义是什么?我认为没有一个有效的,所以这可能就是为什么它不存在。
答案 3 :(得分:2)
什么是无效的?没什么,空虚。 Void32,哈哈! void用于指定不返回任何内容的函数。在其他语言中有关键字'procedure'或'sub'。指向void的指针是指向未知的指针(void的第二种用法)。这有两个目的无效。
更新:我认为,作者想要指定已知大小的未知类型。 void32 *是指向某个大小为32位的实体的指针,void8 *是指向8位实体的指针,依此类推。但它很容易用int32 *,char *模拟,没有语言扩展。
答案 4 :(得分:2)
您正在寻找的东西已经存在。它被称为char
。可以使用char
数组来存储未知对象,因为char
基本上是C ++的一个字节名称。因此,要将未知或可变类型的对象存储到单个数组中,您将使用一个字节数组,而不是一个无数组,void
将是。
void
指针中的一点是我们知道指向的内容。我们不知道它指向的对象的大小。所以void4
没有多大意义。如果我们知道对象的大小,它就不再是“无效”。我们对未知对象唯一能做的就是指向它。我们不能将它存储在任何地方,因为我们不知道它是否是POD对象,我们不知道它有多大或它的对齐要求。所以我们当然不会将它存储到数组中。我们所能做的只是创建一个指向它的指针,我们已经有了void
指针。
当然,这是一个有趣的小问题:
这里的T型是什么?
void foo(void* p) {
T q = *p;
}
void4
? void32
?或者只是void
?物体有多大?我们对此了解多少?它是POD类型吗?
答案 5 :(得分:0)
拥有void数据类型会使事情变得更加复杂。而且如果它被称为void,那么数据类型会做什么。
我猜你指的是一个可能像虚空一样的数据类型,但是你可能想要更改名称而不是将其称为无效。
答案 6 :(得分:0)
void*
不是 void的指针,如无效。它是指向 void的指针,因为那里没有任何东西。
类型类型void
本身是由缺少值定义的。其表示中没有位。它不能形成对象。
您所描述的内容可以进出。因此它包含信息。因此,这不是空洞。
您所描述的仅仅是int
,其中忽略数值。但建议的用途是不好的做法。
答案 7 :(得分:0)
void
是一种“无人居住”类型,这意味着没有类型void
的可能值。由于没有可能的值,因此不需要空间来存储void
。因此,大小void
的值将毫无意义。
退一步:C和C ++相当一致地认为void
意味着“没有”。你可以拥有一个指向任何东西的指针,并使用它来携带一个指针周围的东西的值,但你不能取消引用它 - void
没有你可以做任何事情的价值。
同时注意void
- is-nothing贯穿于void指针的情况:虽然某些编译器(如GNU)允许您对void*
值进行指针算术,就好像它们是{{ 1}},标准禁止在char*
上使用指针算法,因为void*
没什么,它没有任何有意义的大小。
所以,我认为答案是:这将毫无意义。 void
没什么,你不能在值中存储任何东西。
答案 8 :(得分:0)
我会假设你对存储的东西有更多的了解,而不仅仅是它们的尺寸,否则我不相信存储这些东西有多大意义。
我想你可能想看看工会。联盟保留足够的空间来容纳联盟中最大的成员,然后根据您引用联盟的方式,选择“适当”的空间量并将其作为您请求的类型提供给您。
也就是说,就像将一组角色投射到你实际想要的任何类型一样,你应该在使用这种功能之前先思考。
答案 9 :(得分:0)
如果有一个void数据类型,我认为它应该代表什么,只是吞下存储在其中的任何内容。
你可以说(void)func1();
所以为什么不
void x;
x = func1();
或
void func2() {
void x;
...
return x;
}
和作为函数参数
int func3(int x, void y, char z);
void x = func3(1,2);
x = func3(1,x,2);
在表达式中使用void是一个错误
我可以在一些模板编码中看到这个用途。