0

我正在玩自己的堆类。我的模板堆类需要在模板类型上定义运算符“>”和“<”。

使用我编写的示例类的实例时,一切似乎都运行良好(并且在 int 上也运行良好)。但是,由于随着类实例从堆中的不同节点移动,实例的构造如此之多,所以我决定看看当我创建我的类的 shared_ptr 的堆时发生了什么。虽然我确实看到构造的实例数量下降了,但堆没有正常工作,因为它似乎智能指针“>”和“<”被调用,我猜这只是比较智能指针引用。

想到的一种解决方案是允许比较类型,就像许多 stl 类型一样,这样我就可以将自己的比较类型传递到堆类中,该类将取消引用 shared_ptr 并调用底层类型的操作。

我在 shared_ptr 上阅读的一些文档说它们实现了关系运算符(即 <),以便它们可以用作关联容器中的键。我正在尝试考虑何时可能要使用 shared_ptr 作为密钥,而不是拥有自己的特定密钥。

我的样本类型堆似乎工作正常:

heap<foo> foo_heap(heap_type::max);
for (unsigned int i = 0; i < 10; ++i)
    {
    std::string s = "string ";
    s += ('0' + i);
    foo f(i, s);
    foo_heap.push(f);
    }
cout << "root: " << foo_heap.top() << endl;

将我的示例类包装在一个不起作用的 shared_ptr 中,例如。就我要完成的工作而言,堆约束没有得到满足。

heap<shared_ptr<foo>> foo_heap_smart(heap_type::max);
for (unsigned int i = 0; i < 10; ++i)
    {
    std::string s = "string ";
    s += ('0' + i);
    shared_ptr<foo> f(new foo(i, s));
    foo_heap_smart.push(f);
    }
cout << "root: " << *(foo_heap_smart.top()) << endl;

我的示例 foo 类:

class foo
{
public:
    foo(int value, std::string s) : _value(value), _s(s)
    {
        std::cout << "foo::foo()" << std::endl;
    }

    foo(const foo& f) : _value(f._value), _s(f._s)
    {
        std::cout << "foo::foo(const foo& f)" << std::endl;
    }

    ~foo()
    {
        std::cout << "foo::~foo()" << std::endl;
    }

    virtual void operator=(const foo& f)
    {
        std::cout << "foo::operator=()" << std::endl;
        this->_value = f._value;
        this->_s = f._s;
    }

    virtual bool operator<(const foo& right)
    {
        return this->_value < right._value;
    }

    virtual bool operator>(const foo& right)
    {
        return this->_value > right._value;
    }

    void print(ostream& stm) const
    {
        stm << "value: " << this->_value << ", s: " << this->_s;
    }

private:
    int _value;
    std::string _s;
};

所以我认为很多人都遇到了类似的问题。只是想知道规定的解决方案是什么。正如我所提到的,我想我知道出现的可能是一个很好的解决方案,但我想检查一下,智能指针似乎可能会因为它们实现关系运算符而导致许多问题。

谢谢,尼克

4

1 回答 1

1

如果默认的比较运算符不适合您的需要,则规定的解决方案是提供您自己的比较运算符版本。一个更好的heap类设计是也采用一个Comparator类型,它可以默认为std::less.

template <typename T, typename Comp = std::less<T>>
class heap {
...
};

现在为您提供自己的less专门用于shared_ptr.

template <typename T>
struct less<shared_ptr<T>> {
    bool operator()(const shared_ptr<T>& a, const shared_ptr<T>& b) const {
      *a < *b;
    }
};

为了更好的设计,您不能添加一些元编程技巧以使其仅适用于T可以比较的类型。

于 2017-02-15T18:40:23.887 回答