在priority_queue上进行interpret_cast,以遍历非标准的底层向量

Is reinterpret_cast on priority_queue to iterate through the underlying vector non-standard?

本文关键字:非标准 遍历 向量 cast queue priority interpret      更新时间:2023-10-16

下面的代码编译和运行都很好,但我一直在阅读reinterpret_cast,我真的不知道它是否符合标准并且是可移植的。在我看来,这应该是因为我们明确指定了priority_queue的底层容器,但我还没有得到一个直接的答案,所以so向导可能会对这篇文章有一些了解。

它所做的基本上是创建一个优先级队列,该队列使用向量处理整数。然后,它将_cast的该队列重新解释为向量指针,以便可以迭代队列的元素(因为priority_queue本身不包括该功能)。

#include <iostream>
#include <vector>
#include <queue>

int main() {
    std::priority_queue< int, std::vector<int> > pq;
    pq.push(100);
    pq.push(32);
    pq.push(1);
    auto o = reinterpret_cast<std::vector<int> *>(&pq);
    for (std::vector<int>::iterator it = (*o).begin(); it != (*o).end(); it++) {
        std::cout << (*it) << std::endl;
    }
    return 0;
}

标准不保证std::priority_queue类的布局。如果这对您的实现有效,那一定是因为std::vector存储在std::priority_queue对象的开头,但这肯定是不可靠的。

正确的做法是编写自己的std::priority_queue变体(<algorithm>标头已经包含必要的堆算法,如std::push_heap),或者从std::priority_queue派生一个类,这使您可以访问引用底层容器的受保护成员c

下面的代码编译并运行得很好

啊!那是幸运的。

但我一直在阅读relpret_cast,我真的不知道它是否符合标准

是的,是

并且是便携式的。

几乎从来没有。当然不是你使用它的方式。这是一种"如果你不知道它是如何工作的,就不要碰它"的东西。

你可以方便地重新解释将A*投射到空*,然后返回到A*。。。除此之外(好吧,还有一些用例,但它们是特定的,在你玩这根特定的炸药之前,你需要了解它们)。

在我看来,这应该是因为我们明确指定了priority_queue的底层容器,但我还没有得到一个直接的答案,所以so向导可能会对这篇文章有一些了解。

std::priority_queue是底层容器的一个特定的改编。因为队列的正确操作取决于您是否篡改底层容器,所以队列的接口会故意对您隐藏它。

它所做的基本上是创建一个优先级队列,该队列使用向量处理整数。然后,它将_cast的该队列重新解释为向量指针,以便可以迭代队列的元素(因为priority_queue本身不包括该功能)。

它真正做的是调用未定义的行为,这使得它不再可能对程序的任何部分的结果进行推理。如果它对你的环境有效,那就太可惜了。因为现在你会很想把它释放到我的记忆中,在那里它可能不会,或者可能会持续一段时间——同时默默地污染我的记忆,直到。。。轰!我的进程核心转储,我们都不知道为什么。