在STD中崩溃:: Sort-分类而没有严格的弱排序
Crash in std::sort - sorting without strict weak ordering
我正在尝试对项目进行分类。如代码注释中所述,订购应为:
具有更多动作点(mAp
(的参与者首先。当有领带时,与战斗的发起人(mBattleInitiator
(的参与者(mDisposition
(首先。
以下代码(简化示例(在MacOS上崩溃,大概是由于我的排序实现不正确:
#include <QtCore>
class AiComponent
{
public:
enum Disposition {
Friendly,
Hostile
};
AiComponent(Disposition disposition) : mDisposition(disposition) {}
~AiComponent() { qDebug() << "Destroying AiComponent"; }
Disposition mDisposition;
};
class BattleManager
{
public:
BattleManager() : mBattleInitiator(AiComponent::Hostile) {}
class Turn {
public:
Turn() : mAp(1) {}
Turn(QSharedPointer<AiComponent> aiComponent) :
mAiComponent(aiComponent),
mAp(1)
{
}
Turn(const Turn &rhs) :
mAiComponent(rhs.mAiComponent),
mAp(1)
{
}
QSharedPointer<AiComponent> mAiComponent;
int mAp;
};
void addToTurnQueue(QSet<QSharedPointer<AiComponent>> aiComponents);
AiComponent::Disposition mBattleInitiator;
QVector<Turn> mTurnQueue;
Turn mActive;
};
void BattleManager::addToTurnQueue(QSet<QSharedPointer<AiComponent> > aiComponents)
{
foreach (auto aiComponent, aiComponents) {
mTurnQueue.append(Turn(aiComponent));
}
// Sort the participants so that ones with more action points (mAp) go first.
// When there is a tie, participants with the same disposition (mDisposition)
// as the initiator of the battle (mBattleInitiator) go first.
std::sort(mTurnQueue.begin(), mTurnQueue.end(), [=](const Turn &a, const Turn &b) {
if (a.mAp > b.mAp)
return true;
if (a.mAp < b.mAp)
return false;
// At this point, a.mAp is equal to b.mAp, so we must resolve the tie
// based on mDisposition.
if (a.mAiComponent->mDisposition == mBattleInitiator)
return true;
if (b.mAiComponent->mDisposition == mBattleInitiator)
return false;
return false;
});
}
int main(int /*argc*/, char */*argv*/[])
{
BattleManager battleManager;
for (int i = 0; i < 20; ++i) {
qDebug() << "iteration" << i;
QSet<QSharedPointer<AiComponent>> participants;
AiComponent::Disposition disposition = i % 2 == 0 ? AiComponent::Hostile : AiComponent::Friendly;
QSharedPointer<AiComponent> ai(new AiComponent(disposition));
participants.insert(ai);
battleManager.addToTurnQueue(participants);
}
// This should print (1 1), (1 1), ... (1 0), (1 0)
foreach (auto turn, battleManager.mTurnQueue) {
qDebug() << "(" << turn.mAp << turn.mAiComponent->mDisposition << ")";
}
return 0;
}
我已经研究了有关该主题的其他答案。他们中的大多数只是说"将其实施为a> b",就我而言,这将无法使用。有一些看起来很重要,但没有帮助我:
- https://stackoverflow.com/a/16824720/904422-说其他标准算法将起作用,但没有提及任何具体示例
- https://stackoverflow.com/a/33508373/904422-令人困惑,看起来像Overkill
最简单的实现我追求的方法是什么?
尚未解释崩溃的原因。STD :: Sort的大多数实现都是基于快速排序的,特别是Hoare分区方案,只要元素值&lt;只要元素值>枢轴值,枢轴值并从左向左扫描数组。这些扫描指出了以下事实:找到元素值=枢轴值将停止扫描,因此没有检查数组边界之外的扫描检查。如果用户提供的少于比较函数在相等元素的情况下返回true,则两个扫描都可能超出数组边界并导致崩溃。
在调试构建的情况下,可以对用户比较函数进行测试,以确保比较小于和不小于或相等,但对于发布构建,目标是速度,因此这些检查是未执行。
我将在您的代码中发表评论,并解释它的问题(如果有的话(,以及如何修复它。
// Sort the participants so that ones with more action points (mAp) go first.
到目前为止很好
// When there is a tie, participants with the same disposition (mDisposition) as the initiator of the battle (mBattleInitiator) go first.
两个参与者的处置与发起者相同,该怎么办?即使您可以保证没有两个要素可以满足此条件,允许排序算法可以比较自己的元素。在这种情况下,该测试将返回true
,违反了严格的订购条件之一,这是一个元素必须比较与自身相等的情况(即compare(a,a)
必须始终为false(。
也许相反,您想说的是,如果a
具有与启动器相同的处置,并且b
不具有相同的性格,则应将a
视为小于b
。这可以编码为:
return dispositionOfA == mBattleInitiator && dispsitionOfB != mBattleInitiator;
,您的完整测试看起来像这样:
if (a.mAp > b.mAp)
return true;
if (a.mAp < b.mAp)
return false;
return a.mAiComponent->mDisposition == mBattleInitiator &&
b.mAiComponent->mDisposition != mBattleInitiator;
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- std::sort()函数无法对向量的一部分进行排序
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 使用 std::sort 对向量进行稳定排序
- std::排序在共享指针的向量上
- 如何根据排序索引的向量对 std::index 集进行排序?
- 如何按键对 std::对列表进行排序?
- 使用 std::vector C++快速排序,EXC_BAD_ACCESS代码 2
- 为什么我的函数接受"std::string"进行排序不会改变它?
- 如何在 c++11 中静态断言 std::array 类成员进行排序?
- 使用 std::sort 对二维 c 数组进行排序
- std::tuple 可以根据其值在编译时/运行时排序吗?
- 如何排序 std::p空气优先
- 仅当条件适用时才排序 - std::sort
- 排序 std::set 使用 operator() 对插入进行排序
- C++ - 排序 std::vector 中元素的索引
- 合并排序 std:string 中的字符
- 部分排序 std::list