3

我想知道,为什么不能有一个不是指针的 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 指针。

4

10 回答 10

8

它被称为 boost::variant 或 boost::any。它是最大允许数据类型 + sizeof(pointer) 的大小,并且是完全类型安全的。

于 2010-08-25T12:03:58.837 回答
3

在强类型语言中,所有数据都有类型,因此没有“void”作为数据类型的概念。在 C 和 C++ 中,它的含义要么是“无数据”(作为返回值),要么是“您不知道类型的数据”(作为指针目标)。

您提出了一种“您不知道其类型但您知道其大小的数据”的中间状态,大概是您按值传递的类型的不透明版本。除了这是一件相当危险的事情(因为当您更改实际类型的大小时,您必须使用 opaque 类型手动更新所有代码),这已经可以在不添加奇怪的语言扩展的情况下完成,例如:

struct void8 { char bytes[8]; };

可以与您建议的方式结合使用reinterpret_cast,将 POD 类型作为不透明块传递。将它与非 POD 类型一起使用比用于引用非 POD 类型更有可能调用未定义的行为void*

将不透明类型作为指针或对已声明但未定义的命名类型的引用来处理,或者boost::any如果您想要值语义,则将更加安全和惯用。在 C++ 中很少需要使用“void”作为占位符类型。

于 2010-08-25T11:55:03.430 回答
2

“void”数据类型的含义是什么?我不认为有一个有效的,所以这可能就是它不存在的原因。

于 2010-08-25T11:39:00.603 回答
2

什么是空?什么都不是,空虚。Void32,哈哈!void 用于指定不返回任何内容的函数。在其他语言中,有关键字“过程”或“子”。指向 void 的指针是指向未知的指针(void 的第二种用法)。这是 void 服务的两个目的。

更新:我认为,作者想用已知大小指定未知类型。void32* 是指向某个大小为 32 位的实体的指针,void8* 是指向 8 位实体的指针,依此类推。但它很容易用 int32*、char* 模拟,无需语言扩展。

于 2010-08-25T11:39:35.027 回答
2

您正在寻找的东西已经存在。它被称为char。数组char可用于存储未知对象,因为 achar基本上是 C++ 的字节名称。因此,要将未知或可变类型的对象存储到单个数组中,请使用字节数组,而不是空数组void

指针中的要点void是我们不知道它指向什么。我们也不知道它指向的对象的大小。所以 avoid4没有多大意义。如果我们知道对象的大小,它就不再是“无效的”。对于未知对象,我们唯一能做的就是指向它。我们不能将它存储在任何地方,因为我们不知道它是否是 POD 对象,也不知道它有多大,或者它的对齐要求。所以我们当然不会将它存储到数组中。我们所能做的就是创建一个指向它的指针,我们已经有了指向它的void指针。

当然,还有一个有趣的小问题:

这里的 T 型是什么?

void foo(void* p) {
   T q = *p;
}

void4? void32? 还是只是void?物体应该有多大?我们对它了解多少?它是 POD 类型吗?

于 2010-08-25T11:56:01.800 回答
0

拥有一个 void 数据类型会使事情变得不必要地复杂化。此外,如果数据类型被称为 void,它会做什么。

我猜您指的是一种可能像 void 一样运行的数据类型,但您可能想要更改名称而不是称其为 void。

于 2010-08-25T11:42:20.397 回答
0

void*不是无效的指针如无效。它是一个指向void的指针,因为那里什么都没有。

类型类型void本身是由缺少值定义的。它的表示中没有位。它不能形成物体。

您所描述的内容可以来回转换。因此它包含信息。因此,它不是一个空虚。

你所描述的只是一个int数值被忽略的地方。但建议的用途是不好的做法。

于 2010-08-25T12:04:23.920 回答
0

void是“无人居住”类型,这意味着 type 没有可能的值void。由于没有可能的值,因此存储 a 不需要空间void。因此,大小void值将毫无意义。

退后一步:C 和 C++ 相当一致地认为void是“无”的意思。您可以有一个指向任何内容的指针,并使用它来携带指向周围某物的指针的值,但您不能取消引用它 -void没有可以做任何事情的值。

还要注意void-is-nothing 会延续到 void 指针的情况:虽然某些编译器(例如 GNU)允许您对void*值进行指针运算,就好像它们是一样char*,标准禁止指针运算,void*因为,因为void什么都没有,它有没有有意义的大小。

所以,我认为答案是:这将毫无意义。 void什么都不是,你不能在一个值中存储任何东西。

于 2010-08-25T12:08:42.633 回答
0

我将假设您对将要存储的东西了解更多,而不仅仅是它们的大小,否则我认为存储这些物品没有多大意义。

我想你可能想看看工会。联合保留足够的空间来容纳联合的最大成员,然后根据您引用联合的方式,选择“适当”的空间量并将其作为您请求的类型提供给您。

也就是说,就像将一组字符转换为您实际要查找的任何类型一样,您应该在使用此类功能之前仔细考虑。

于 2010-08-25T12:13:12.677 回答
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 是错误的

我可以在一些模板编码中看到它的用途。

于 2010-08-25T12:26:05.517 回答