的std :: priority_queue ::顶部 返回一个常量值。但是,我想从优先级队列中删除顶部元素,并能够在其他地方修改它。
priority_queue<SomeClass, vector<SomeClass>, SomeClassCompare > pQueue;
...
SomeClass *toBeModified = &(pQueue.top());
pQueue.pop();
toBeModified->setMember(3); // I would like to do this
有没有办法可以从优先级队列中获取顶级元素(并从队列中删除)并按照我的意愿修改它?
标准容器和容器适配器 价值语义。将元素推入队列时,会创建一个副本。从队列中删除对象时,该对象将被销毁。
即使 top()
会给你一个非const
,一旦从队列中删除该元素,该引用将变为悬空,并且取消引用它将导致未定义的行为。
这说, std::priority_queue
返回引用 const
为了防止你(有意或无意地)弄乱其内部排序 - 这与关联容器的关键,例如 std::map
和 std::set
是 const
。
相反,你可以做的是构建一个 复制 返回的值 top()
,修改该副本,删除原始副本,并将副本推送到队列中:
SomeClass obj = pQueue.top();
pQueue.pop();
obj.setMember(42);
pQueue.push(std::move(obj)); // You can move obj into the queue if you no more need it
如果你需要 引用语义另一方面,那么你将不得不推动 指针 进入队列(可能是智能指针,具体取决于您的用例)并提供适当的自定义排序标准,该标准将根据指向的对象的属性对这些指针进行排序。
在这种情况下,请注意不要在运行时修改这些属性,使其顺序不同。这算作“搞乱容器的内部排序“,并将导致未定义的行为。
标准容器和容器适配器 价值语义。将元素推入队列时,会创建一个副本。从队列中删除对象时,该对象将被销毁。
即使 top()
会给你一个非const
,一旦从队列中删除该元素,该引用将变为悬空,并且取消引用它将导致未定义的行为。
这说, std::priority_queue
返回引用 const
为了防止你(有意或无意地)弄乱其内部排序 - 这与关联容器的关键,例如 std::map
和 std::set
是 const
。
相反,你可以做的是构建一个 复制 返回的值 top()
,修改该副本,删除原始副本,并将副本推送到队列中:
SomeClass obj = pQueue.top();
pQueue.pop();
obj.setMember(42);
pQueue.push(std::move(obj)); // You can move obj into the queue if you no more need it
如果你需要 引用语义另一方面,那么你将不得不推动 指针 进入队列(可能是智能指针,具体取决于您的用例)并提供适当的自定义排序标准,该标准将根据指向的对象的属性对这些指针进行排序。
在这种情况下,请注意不要在运行时修改这些属性,使其顺序不同。这算作“搞乱容器的内部排序“,并将导致未定义的行为。
我不认为价值语义在这里起任何作用。所有其他容器具有相同的值语义,几乎所有容器都提供 front()
有可变参考。
有一个确切的原因 priority_queue
不允许修改 top()
element:这是因为特定元素位于顶部,因为根据其现值,它已经相应地合格。优先级队列中的元素是 总是排序 根据为队列配置的比较条件(默认情况下为operator <)。通过更改元素,您可能会破坏此条件,并导致使用已排序前置条件的所有操作都将导致未定义的行为。
总之,之所以如此 priority_queue
不允许修改包含的元素与情况完全相同 set
和钥匙 map
。
我知道你可能有一些专用的比较方法,你使用一个包含比较值的字段,你将修改该对象的任何内容,除了这个字段。这样您就不会违反排序顺序的要求。你可以做两件事:
使你的班级的部分应该被修改为 mutable
。这样你就可以获得元素了 top()
并修改可变内容,即使这是const。
通过派生创建自己的优先级队列类 std::priority_queue
。它有一个名为的字段 c
(在 保护 虽然部分),其中包含对底层容器的引用 - 而底层容器总是有一个 front()
访问相同元素的方法 top()
在 priority_queue
。但是,为了您自己的安全,您应该成为关键领域 const
,因此它在施工期间设置并且从未改变 - 只是为了将风险降至最低。
啊,这个问题也不能通过使用指针来解决 - 指向对象将是完全相同的常量。这些“引用语义”也不会对你有任何帮助,因为如果你想要一个专用的比较方法,就必须查看对象的内容,这样你就会遇到完全相同的问题。如果您依靠简单地比较指针值,这对您有所帮助,但我更怀疑这可能是99%案例的解决方案。