繁体   English   中英

为什么 std::set::insert() 调用带有错误参数的 operator<()

[英]Why does std::set::insert() call operator<() with bad parameter

我需要帮助来理解为什么std::set<T>::insert(T) operator<(const T&, const T&)使用无效引用作为第二个参数调用operator<(const T&, const T&) ,在我第一次插入时创建段错误。

这是我想在集合中插入其对象的类:

/**
 * A CPC category.
 */
class Category {

  private:
    char m_section;
    int  m_class;
    char m_subclass;
    int  m_group;
    int  m_subgroup;

  public:
    Category();
    Category(char t_section, int t_class, char t_subclass, int t_group,
             int t_subgroup);
    char get_section() const;
    int  get_class() const;
    char get_subclass() const;
    int  get_group() const;
    int  get_subgroup() const;

};

这是我的operator< (抱歉,这不是有史以来最干净的方法):

/**
 * Obeys simple lexical order. A smaller-than operator for Category is
 * required to allow objects to be placed in an std::set.
 */
bool operator<(const Category& cat1, const Category& cat2)
{
    return (cat1.get_section() == cat2.get_section() ?
                cat1.get_class() == cat2.get_class() ?
                    cat1.get_subclass() == cat2.get_subclass() ?
                        cat1.get_group() == cat2.get_group() ?
                            cat1.get_subgroup() == cat2.get_subgroup() ?
                                true :
                                cat1.get_subgroup() < cat2.get_subgroup() :
                            cat1.get_group() < cat2.get_group() :
                        cat1.get_subclass() < cat2.get_subclass() :
                    cat1.get_class() < cat2.get_class() :
                cat1.get_section() < cat2.get_section());
}

这是创建集合的代码:

std::istream& operator>> (std::istream& is, CategorySet& cs)
{
    std::set<Category>* cats;
    Category cat;
    while (is >> cat) {
        cats->insert(cat);
    }   
    cs = CategorySet{ cats };
    return is;
}

我在cats->insert(cat);之前放置了一个断点cats->insert(cat);

Breakpoint 1, InnovationModelling::operator>> (is=..., cs=...) at lib/PatentData.cpp:126
126         cats->insert(cat);
(gdb) p *cats
$9 = std::set with 0 elements
(gdb) p cat
$1 = {m_section = 65 'A', m_class = 1, m_subclass = 65 'A', m_group = 1, m_subgroup = 0}
(gdb) ptype cat
type = class InnovationModelling::Category {
  private:
    char m_section;
    int m_class;
    char m_subclass;
    int m_group;
    int m_subgroup;

  public:
    Category(void);
    Category(char, int, char, int, int);
    char get_section(void) const;
    int get_class(void) const;
    char get_subclass(void) const;
    int get_group(void) const;
    int get_subgroup(void) const;
}

(上面的$9是因为我忘记显示此时集合是空的,所以我第二次运行该程序。)

然后我遍历std::set的东西,直到它调用operator() ,它没有重载:

(gdb) s
std::less<InnovationModelling::Category>::operator() (this=0x5555555993c0 <std::cout@@GLIBCXX_3.4>, __x=..., __y=...)
    at /usr/include/c++/10.2.0/bits/stl_function.h:386
386       { return __x < __y; }
(gdb) p __x
$2 = (const InnovationModelling::Category &) @0x7fffffffd3b0: {m_section = 65 'A', m_class = 1, m_subclass = 65 'A', m_group = 1, 
  m_subgroup = 0}
(gdb) p __y
$3 = (const InnovationModelling::Category &) <error reading variable>

果然, operator<被这个无效的引用调用,因此get_section()最终被调用它并出现段错误:

(gdb) s
InnovationModelling::Category::get_section (this=0x26) at lib/PatentData.cpp:187
187     return m_section;
(gdb) p this
$7 = (const InnovationModelling::Category * const) 0x26
(gdb) p *this
Cannot access memory at address 0x26
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x0000555555568412 in InnovationModelling::Category::get_section (this=0x26) at lib/PatentData.cpp:187

如果std::set::insert()正在做什么很明显,我很抱歉,但我是 C++ 的初学者,我什至无法理解感觉需要调用的事实operator<()在空集合中插入一些东西。

这是创建集合的代码:

'怕不是。

您创建了一个指向集合的指针,但它实际上并不指向任何集合; 它只是一个未初始化的指针。

您可以使用new来动态分配一个集合,但除非必须,否则不要这样做。 事实上,除非必须,否则不要使用指针。 您在这里的需求将由CategorySet驱动(我们对此一无所知),但是如果您可以让您的集合成为一个不错的局部变量,那么生活就会容易得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM