为什么void *不是迭代器类型?

时间:2013-10-20 20:46:18

标签: c++ gcc iterator

我已经使用GCC 4.8测试了以下代码,但由于我们无法形成对void的引用,因此无法编译。

#include <iterator>
int main()
{
    std::iterator_traits<void*> test;
}

这是否意味着void *不是iterator? (意思是这里的概念)

修改

好的问题是形成不良。我实际上问的是为什么C ++需要void *的这种行为?是出于安全考虑,即阻止人们写坏事吗?

因为虽然引用void是非法的,但指针算术是:

int main()
{
    std::uint8_t test[] = {1,2,3};
    void * wut = test;
    std::uint8_t * p2 = static_cast<std::uint8_t *>(wut + 1);
    std::cout << std::hex << static_cast<int>(*p2) << std::endl; 
}

因此,正如你所说,从GCC的角度来看,空虚的规模并不大,确实如此。它是计算机中最小的可加压单元的大小。

3 个答案:

答案 0 :(得分:30)

任何迭代器类型都需要可解除引用且可递增,但您不能取消引用或增加void*。自从您关联cppreference.com后,它就会启动here


关于您更新的问题:出于安全原因。如果你想要一个指向内存中各个字节的指针,你可以使用char*unsigned char*或类似的东西。 void*基本上只是一种存储地址的方式,它不应该被用来访问任何东西。只有当你知道它指向的是什么时,你才应该将它转换为指向该类型的指针。

允许您添加(或减去)的原因是AFAIK是为了向后兼容。对于void* p;,您可以编写p += 1;,但 允许您使用++p;

增加<{1}}
  

5.3.2递增和递减[expr.pre.incr]

     

1 前缀++的操作数通过添加1进行修改,如果是true则设置为bool(此用途为不建议使用)。操作数应是可修改的左值。操作数的类型应为算术类型或指向完全定义的对象类型的指针。

(强调我的)。

答案 1 :(得分:13)

为什么你不能拥有void类型的迭代器?

§3.9.1/9§5.7,类型void不是完整类型,添加运算符不能应用于不完整的指针类型:

  

void类型有一组空值。 void类型是不完整类型,不能是&gt;完成...

     

...操作数是 (必须) 指向完全定义的对象的指针......

因此,您无法获得空洞的迭代器。

为什么你会看到这个错误?

  

错误:形成对void的引用

声明std::iterator_traits,它在某处尝试声明对您的案例中void的条目类型的引用。但是根据§8.3.2/5声明对void的引用是不合法的,因为您无法定义void的有效对象:

  

应初始化引用以引用有效对象

答案 2 :(得分:7)

答案很简单,因为你无法取消引用void*。 void也没有大小,所以你不能移动到下一个项目。迭代器类型必须是增量和可解除引用的。

修改: -

  

是出于安全考虑,即阻止人们写错   事情?

是的,这是出于安全原因。您无法在编辑中执行您尝试执行此操作的操作。 void*仅用于存储地址,如果您使用它来访问任何内容,则不允许这样做。

您可以为wut = wut + 1

撰写void * wut