【问题标题】:runtime error using std map for comparison使用标准映射进行比较的运行时错误
【发布时间】:2018-12-07 08:14:03
【问题描述】:

首先,这里有一个类似的问题:Unusual std::map runtime error

但由于那里没有真正的解决方案,我想再问一次,因为我真的很困惑,无能为力。

我的代码如下:

struct MyObj{
//constructor
MyObj(){}
std::map<std::string, std::string> m_fooMap;

bool operator==(const MyObj& other)
{
    if (m_fooMap.size() != other.m_fooMap.size())
        return false;

    std::map<std::string, std::string>::const_iterator i, j;
    i = m_fooMap.cbegin();
    j = other.m_fooMap.cbegin();
    for (; i != m_fooMap.cend(), j != other.m_fooMap.cend(); ++i, ++j)
    {
        if(i->first.empty() || j->first.empty())
            continue;

        if (i->first != j->first)
            return false;

        if (i->second != j->second)
            return false;
    }

  return true;
}

bool operator!=(const MyObj& other)
{
    return !operator==(other);
}
};

struct AnotherObj{
std::map<std::string, MyObj> m_collectionOfObjs; //always guaranteed to contain atleast one entry

bool operator==(const AnotherObj &other) const
    {
        for (auto& objIt : m_collectionOfObjs)
        {
            auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);

            if (findSeriesIt == other.m_collectionOfObjs.end())
                return false;

            //else found, see if the internal content is the same?
            else
            {
                if (objIt.second != findSeriesIt->second)
                    return false;
            }
        }

        //else
        return true;
    }
};

现在,我有一个 std::vector anotherObjVec; 我需要相互比较这个向量中的项目。我使用 == 运算符。

现在每次都是随机实例,即使输入数据相同,也似乎存在运行时错误。 “xtree”文件中的错误指向以下代码。

_Nodeptr _Lbound(const key_type& _Keyval) const
    {   // find leftmost node not less than _Keyval
    _Nodeptr _Pnode = _Root(); //<------------ THIS line is where it points to
    _Nodeptr _Wherenode = this->_Myhead;    // end() if search fails

    while (!this->_Isnil(_Pnode))
        if (_DEBUG_LT_PRED(this->_Getcomp(), this->_Key(_Pnode), _Keyval))
            _Pnode = this->_Right(_Pnode);  // descend right subtree
        else
            {   // _Pnode not less than _Keyval, remember it
            _Wherenode = _Pnode;
            _Pnode = this->_Left(_Pnode);   // descend left subtree
            }

    return (_Wherenode);    // return best remembered candidate
    }

我被困住了,不知道下一步该做什么。我什至尝试像这样启动构造函数:

MyObj() : m_fooMap(std::map<std::string, std::string>()){}

使用 C++11,Visual Studio 2012(v110)

【问题讨论】:

  • 确实没有答案,除了应该是评论的答案。我这样标记了这个答案,你可能也想这样做 deathNode 。祝你好运!
  • @gsamaras 我仍然对那条评论感到困惑。我的地图是结构 MyObj 的成员变量。我不确定问题到底出在哪里。我应该如何实例化地图?请您提供更多说明吗?
  • 我的意思是您链接的问题中发布的答案确实不是答案(应该是评论)。但是,我没有时间研究您的问题,抱歉(其他人肯定会这样做,这就是我说祝你好运的原因!)。
  • @rafix07 这是完整的代码。然而,“else if”是一个错字。感谢您指出这一点,我已解决。

标签: c++ c++11 stdmap


【解决方案1】:

您正在比较来自不同地图的迭代器:

auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);
if (findSeriesIt == m_collectionOfObjs.end())
    return false;

findSeriesIt 来自other.m_collectionOfObjs 映射,但您将其与m_collectionOfObjs 的末尾进行比较。应该是:

auto findSeriesIt = other.m_collectionOfObjs.find(objIt.first);
if (findSeriesIt == other.m_collectionOfObjs.end())
    return false;

【讨论】:

  • 哦,当然,这是一个重大错误。但话虽如此,它仍然不能解决问题。但是感谢您指出这一点,我将其编辑到我的问题中的代码中
【解决方案2】:

你的话

即使输入数据相同,但似乎有一个运行时 错误。

所以看起来operator==应该在块的末尾返回true,但是你的函数没有返回任何值(如果你的地图是空的,你的函数到达没有返回语句的块的末尾):

bool operator==(const MyObj& other)
{
    if (m_fooMap.size() != other.m_fooMap.size())
        return false;

    std::map<std::string, std::string>::const_iterator i, j;
    i = m_fooMap.cbegin();
    j = other.m_fooMap.cbegin();
    for (; i != m_fooMap.cend(), j != other.m_fooMap.cend(); ++i, ++j)
    {
        if(i->first.empty() || j->first.empty())
            continue;

        if (i->first != j->first)
            return false;

        if (i->second != j->second)
            return false;
    }
  // ??? return is missing here
}

所以它是未定义的行为

(from):

从返回值函数的末尾流出(main 除外) 没有返回语句是未定义的行为。

【讨论】:

  • 这是一个有效的点。它编译。我修好了,谢谢:),但这仍然不能解决问题。
【解决方案3】:

i != m_fooMap.cend(), j != other.m_fooMap.cend() 使用逗号运算符,丢弃第一个操作数。它不会检查这两个条件,因此当i 等于结束迭代器时,它可能会在以后被取消引用。您应该改用and 运算符:

(m_fooMap.cend() != i) and (other.m_fooMap.cend() != j);

【讨论】:

  • 我认为检查地图的大小是否相等应该照顾它。随着迭代器的增加,它们都应该具有相同的元素编号。但是,我按照您提到的那样编辑了代码,问题仍然存在。
【解决方案4】:

原来地图没有正确实例化。这发生在我身上,因为我正在使用 std::shared_ptr 并将其存储在 std::vector 中。然后迭代它,共享ptr之一是nullptr。不知道为什么会这样,因为它是一个共享的 ptr,并且它在向量中应该仍然保持引用计数,但我只是更改了向量的迭代技术,它现在可以工作了。

【讨论】:

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