【问题标题】:The std::less<int>()(int, int) might get a wrong answerstd::less<int>()(int, int) 可能会得到错误的答案
【发布时间】:2020-08-18 04:50:01
【问题描述】:

我正在学习 SplayTree。当我编写代码时,我得到了标题所说的错误。这个错误出现在我的“splay”方法中:

void splay(const KeyType& arg_key, Node*& tree)

这一行:

if (key_less(arg_key, key(tree)))

我试图输出一些关于这一行的消息,发现它总是得到一个“真实”的答案

代码:
std::cerr << "arg_key == " << arg_key << "; key(tree) == " << key(tree) << std::endl;
std::cerr << "key_less(arg_key, key(tree)) == " << key_less(arg_key, key(tree)) << std::endl;
std::cerr << "key_less(key(tree), arg_key) == " << key_less(key(tree), arg_key) << std::endl;
std::cerr << "typename of key_less == " << typeid(key_less).name() << std::endl;

输出:

arg_key == 2; key(tree) == 8
key_less(arg_key, key(tree)) == 0
key_less(key(tree), arg_key) == 1
typename of key_less == struct std::less<int>

splay树模板是这样的

template <typename KeyType, typename ValueType, typename KeyOfValue, typename Comparator = std::less<KeyType>> class SplayTree

我定义了一个展开树

struct GetKeyFromValue
{
    int operator()(int value)
    {
        return value;
    }
};
SplayTree<int, int, GetKeyFromValue, std::less<int>> tree;

当我将最后一个模板参数更改为

    struct Comparator
    {
        bool operator()(int lhs, int rhs)
        {
            return lhs < rhs;
        }
    };
    SplayTree<int, int, GetKeyFromValue, Comparator> tree;

它可以得到正确的答案:

arg_key == 2; key(tree) == 8
key_less(arg_key, key(tree)) == 1
key_less(key(tree), arg_key) == 0
typename of key_less == struct `int __cdecl main(void)'::`2'::Comparator

这是一个错误吗?

非常感谢您关注我的问题。

我非常期待您的帮助。

附: 我的平台是 Windows10 1909 上的 Visual Studio 2019 16.7.1。

【问题讨论】:

  • 从表面上看,它看起来像一个错误,但缺少的代码太多无法确定。你需要拼凑一个minimal reproducible example
  • 很难想象std::less 会错误地比较两个ints 的情况。它易于实现,易于验证,并且有足够多的程序员会使用它,以至于很久以前就会检测到错误。几乎可以肯定,问题出在您未显示的某些代码中。假设 arg_keyint,一个候选者是 key(tree) 返回的类型具有某些行为(例如,operator int() 的工作),这与您的假设不同。
  • 正如@Peter 提到的,很难相信std::less&lt;int&gt; 会有错误。 Visual Studio 附带一个调试器,你应该在比较发生的地方设置一些条件断点,然后自己看看。

标签: c++ stl


【解决方案1】:

感谢@Peter!正如您所提到的,问题发生在key(tree)。它的定义是

static const KeyType& key(Node* node_ptr) { return KeyOfValue()(node_ptr->value); }

在这种情况下,KeyOfValue 是一个我不小心写的类:

struct GetKeyFromValue
    {
        int operator()(int value)
        {
            return value;
        }
    };

我改成之后

struct GetKeyFromValue
    {
        const int& operator()(const int& value)
        {
            return value;
        }
    };

现在一切正常。 我认为这个问题可能是 key(tree) 返回了 const int&amp;GetKeyFromValue::operator()(int) 返回的临时值的引用?

感谢所有可以阅读我的问题并毫不犹豫地启发我的人。

【讨论】:

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