如何使用用户定义的对象从priority_queue中获取非const顶级元素
How to get a non-const top element from priority_queue with user-defined objects?
std::priority_queue::top
返回一个常量值。但是,我想从优先级队列中删除顶部元素,并能够在其他地方修改它。
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
另一方面,如果您需要引用语义,则必须将指针推入队列(可能是智能指针,取决于您的用例),并提供适当的自定义排序标准,该标准将根据指针指向的对象的属性对这些指针进行排序。在这种情况下,请注意不要在运行时修改这些属性,以免改变它们的顺序。这将被视为"扰乱了容器的内部排序",并将导致未定义的行为。
我认为值语义在这里不起任何作用。所有其他容器都具有相同的值语义,并且几乎所有容器都为front()
提供可变引用。
priority_queue
不允许修改top()
元素有一个确切的原因:这是因为特定元素位于顶部,因为它根据其当前值相应地被限定了。优先级队列中的元素总是根据为队列配置的比较标准(操作符<默认情况下)。通过更改元素,您可能会破坏此条件,并导致所有使用排序前提条件的操作都将导致未定义的行为。>
简而言之,priority_queue
不允许修改包含元素的原因与set
和map
的关键字的情况完全相同。
我知道您可能有一些专用的比较方法,您使用包含要比较的值的字段,并且您将修改对象的任何内容,除了这个字段。这样就不会违反排序顺序的要求。您可以做两件事:
-
将类的部分修改为
mutable
。通过这种方式,您可以通过top()
获取元素并修改可变内容,即使这是const。 -
通过派生
std::priority_queue
创建自己的优先级队列类。它有一个名为c
的字段(尽管在protected section中),其中包含对底层容器的引用-底层容器总是有一个front()
方法,该方法访问priority_queue
中的top()
相同的元素。但是,为了您自己的安全,您应该将密钥字段设置为const
,以便在构建期间设置并且永远不会更改-只是为了将风险降到最低。
啊,这个问题也不能通过使用指针来解决——指向的对象将是完全相同的常量。这些"引用语义"也不会以任何方式帮助您,因为如果您希望有一个专用的比较方法,它将不得不查看对象的内容,这样您将遇到完全相同的问题。如果您仅仅依赖于比较指针值,这将对您有所帮助,但我更怀疑这可能是99%情况下的解决方案。
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 为什么相同的函数签名只有区别,另一个通过 const 获取参数是重新定义?
- 延长函数的寿命延长 由 const& 获取参数并由 const& 返回
- 从本机代码返回"const char*"并在java中获取"字符串"
- 使用const_cast const-ref getter 实现引用获取器的陷阱
- 转换为std :: string并在一行中获取const char *
- 无序地图 - 使用const键获取值
- 获取const lvalue参考的地址是合法的吗?
- 使用 Visual Studio 2013 直接从 std::ostringstream 获取 const char *
- 如何从"const int i"获取i的真实地址
- 如何在不复制或查找的情况下获取 const 字符串流缓冲区的长度?
- 如何在cocos2dx中获取静态const int三维数组长度
- 如何获取对象的const引用并使用该引用更改对象(使用const_cast)
- 如何获取boost::any保存的数据的const引用
- 如何使用用户定义的对象从priority_queue中获取非const顶级元素
- 获取模板类型的基类型(移除const/reference等)
- C++ 为什么 Const& 可以获取 const 值?
- 通过指针获取修饰char*和char const*:很好的实践
- 获取对字符串的子字符串的const访问
- 基于范围的循环:通过值或对const的引用获取项