C ++ Void非指针

时间:2010-08-25 11:36:30

标签: c++ types void casting

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

10 个答案:

答案 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;
}

void4void32?或者只是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是一个错误

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