【问题标题】:Why void* isn't an iterator type?为什么 void* 不是迭代器类型?
【发布时间】:2013-10-20 20:46:17
【问题描述】:

我已经使用 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; 
}

因此,即使如您所说,void 没有大小,但从 GCC 的角度来看,它确实有。它是计算机中最小可寻址单元的大小。

【问题讨论】:

  • 如果void* 是一个迭代器,你将如何获得下一个void*void 没有大小...
  • 避免空虚 - 对它有点好感
  • 更新了我的回答来回答你的更新:)
  • @DanielFrey 感谢您的更新。向后兼容通常会使事情变得比想象的更困难。

标签: c++ gcc iterator


【解决方案1】:

任何迭代器类型都需要是可解引用和可递增的,但您不能解引用或递增void*。由于您链接了cppreference.com,它开始于here


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

允许您添加(或减去)它的原因是 AFAIK 以实现向后兼容性。对于void* p;,您可以编写p += 1;,但不允许按照++p; 递增它

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

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

(强调我的)。

【讨论】:

  • 同样 void 没有大小,那么如何移动到下一个项目(另一种思考方式)?
  • @BobFincheimer 正确,我添加了它。这实际上是 all 迭代器类型的两个常见要求。
【解决方案2】:

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

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

void 类型有一组空值。 void 类型是一个 incomplete 类型,不能>完成...

...操作数是(应该)一个指向完全定义对象的指针...

因此你不能有一个空洞的迭代器。

 

为什么您会看到该错误?

错误:形成对 void 的引用

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

一个引用应该被初始化为引用一个有效的对象

【讨论】:

    【解决方案3】:

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

    编辑:-

    是否出于安全考虑,即防止人们写得不好 东西?

    是的,这是出于安全原因。你不能在你的编辑中做你试图做的事情。 void* 只是用来存储地址,如果你用它来访问任何东西,那么它是不允许的。

    你可以为void * wutwut = wut + 1

    【讨论】:

    • 我收到错误消息 error: pointer of type ‘void *’ used in arithmetic for wunt = wut + 1 for void *wut 。我的 g++ 是 4.2。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多