Я играю вокруг написания своего класса кучи. Мой шаблонный класс кучи требует, чтобы операторы '>' и '<' определялись по типу шаблона.C++ с использованием shared_ptr, но с вызывающими операторами отношения моего объекта?
Все, казалось, отлично работали при использовании экземпляра класса образцов, который я написал (а также отлично работали над 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;
};
Так я предполагаю, что многие из них столкнулись с подобной проблемой. Просто интересно, что такое предписанное решение. Как я уже говорил, я думаю, что я знаю, что может показаться хорошим решением, но хотел проверить, как кажется, что умный указатель может вызвать множество проблем из-за их реализации реляционных операторов.
Спасибо, Ник
Предписанное решение состоит в том, чтобы предоставить свою версию оператора сравнения, если по умолчанию это не подходит. Лучшим дизайном для вашего класса 'heap' будет также использовать тип Comparator, который может по умолчанию использовать' std :: less' – Arunmu
Если вы беспокоитесь о слишком большом количестве копий, вы должны узнать о семантике перемещения, а не о прыгая прямо в 'std :: shared_ptr'. –
@miles, я хотел бы узнать о семантике перемещения. Можете ли вы указать мне некоторые документы?Мне было интересно, есть ли какой-то специальный swap, который я мог бы использовать, чтобы обойти конструктор/деструктор. – nickdu