【问题标题】:Strange shared_ptr comparator selection for priority queue in GCCGCC中优先级队列的奇怪shared_ptr比较器选择
【发布时间】:2018-12-22 04:58:46
【问题描述】:

我有一个包含在std::shared_ptr 中的类,我想在std::priority_queue 的帮助下选择前k 个对象。所以,我定义operator < 并期望一切都会好起来的。但事实并非如此。默认情况下(使用 gcc)std::priority_queue 使用std::shared_ptr 的默认比较器,它比较地址。

但是,如果我将 std::sort 用于 std::vector 而没有指定比较器,则行为会有所不同,我的operator < 将被使用。这有点出乎意料和不一致的行为。

代码示例:

struct document
{   
    float rank;
    document(float rank):
        rank(rank)
    { }
};

using doc_ptr = shared_ptr<document>;

bool operator < (const doc_ptr& x, const doc_ptr& y)
{   
    return x->rank < y->rank;
}

int main()
{
    priority_queue<doc_ptr> pq;
    for(int i = 0; i < 10; i++) {
        float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        pq.push(make_shared<document>(r));
    }

    vector<doc_ptr> pq_v;

    while(!pq.empty()) {
        cout << pq.top()->rank << " " << uint64_t(pq.top().get()) << endl;
        pq.pop();
    }

    return 0;
}

我得到以下输出:

0.277775 35463848
0.76823 35463800
0.335223 35463752
0.197551 35463704
0.55397 35463560
0.911647 35463512
0.783099 35463384
0.79844 35463336
0.394383 35463288
0.840188 35463208

使用 clang(Apple LLVM 版本 9.1.0 (clang-902.0.39.2))一切正常。

std::priority_queuestd::sort 的完整代码用于std::vectorhttps://ideone.com/awsdrO

我想这可能与名称解析有关,但我自己无法找到它。所以,我想知道谁在这里,为什么?

UPD:这里的例子要简单得多:https://ideone.com/wm1YBw 最后一行输出在 gcc 和 clang 中有所不同,因为 gcc 为 shared_ptr 提供了 std::less 的特化,但 clang 没有。

【问题讨论】:

  • 与您的问题无关,但要打印指针,您真的不应该将其转换为任何整数类型。 an operator&lt;&lt; overload 接受 void* 并可用于任何指针。尤其如此,因为指针的大小不必是 64 位(尽管在大多数当前的 64 位系统上恰好是)。如果您真的需要一个指针大小的整数,请使用intptr_t(或uintptr_t)。
  • 感谢您指出。实际上,我只是想将指针从十六进制转换为十进制,我认为它变得更具可读性(也许我错了)。
  • 有趣的事实:sort(v.begin(), v.end(), std::less&lt;doc_ptr&gt;()); 也按指针排序。所以这与通过std::less 的间接性有关。但我不确定为什么。我的猜测是,这个特定的实现(我相信不正确)为shared_ptr 提供了std::less 的专业化。
  • @IgorTandetnik 你是对的。 gcc 为shared_ptr 提供了std::less 的特化,但clang 没有。所以,我们现在可以有一个非常简单的例子:ideone.com/wm1YBw

标签: c++ c++11 gcc stl clang


【解决方案1】:

事实证明,gcc 为 std::shared_ptr 提供了 std::less 的特化,这是不应该提供的。您可以在this 错误报告中找到所有其他详细信息。

如果我理解正确:一些 C++ 标准的早期草案明确提到,应该提供 std::lessstd::shared_ptr 的专门化。工作过程中从标准中删除了这个提及,但在 gcc 代码本身中没有删除。

所以,如果你使用没有修复的 gcc 版本,请小心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多