【发布时间】:2017-08-06 21:26:07
【问题描述】:
我正在尝试将我在 C# 到 C++ 中制作的优先级队列实现重新创建为一个可以跳入 C++ 的项目,但是很多细微差别都让我感到困惑。队列被设计为一个模板,可以在任何给定的类 T 上工作。队列将显式使用一个表示称为优先级对的对象的结构:一个指向 T 对象的指针和一个关联的优先级值 (int)。
这样做的目的是让队列中被比较的实际对象(T's)完全分开并且只被指向。我可能并不明确需要结构来完成此操作,但我就是这样做的。
队列实现的重要部分:
template <class T>
class PriorityQueue
{
public:
PriorityQueue(const int maxSizeIn)
{
maxSize = maxSizeIn;
queueArray = new PriorityPair<T>*[maxSize];
currentHeapSize = 0;
}
~PriorityQueue()
{
cout << "Destroy Queue with size: " << currentHeapSize << endl;
for (int i = 0; i < currentHeapSize; i++)
{
delete (PriorityPair<T>*)queueArray[i];
}
delete[] queueArray;
}
private:
PriorityPair<T>** queueArray;
PriorityPair 的结构:
template <class T>
struct PriorityPair
{
PriorityPair(int valueIn, T* objectIn)
{
_PriorityValue = valueIn;
_Object = objectIn;
};
~PriorityPair()
{
cout << "Destroy Pair for object :(" << *_Object << "): << endl;
}
int _PriorityValue;
T* _Object;
};
在测试过程中,我发现调用 PeekTop 方法似乎会导致 PriorityPair 调用其析构函数。我最好的猜测是,由于无法理解语言的细微差别,我不小心创建了一个临时的。
查看方法如下:
T PeekTop()
{
if (IsEmpty())
return nullptr;
else
return *((PriorityPair<T>)(*queueArray[0]))._Object;
}
另外,这里是插入操作(最低有效的插入,没有堆/队列操作):
int InsertElement(PriorityPair<T>* elementIn)
{
//do not insert nulls --
if (elementIn == nullptr)
return -2;
//we could user std::vector or manually expand the array, but a hard max is probably sufficient
if (currentHeapSize == maxSize)
{
return -1;
}
//insert the pointer to the new pair element in at the index corresponding to the current size, then increment the size
queueArray[currentHeapSize++] = elementIn;
return 0;
}
我主要有以下几点:
PriorityQueue<string> queue = PriorityQueue<string>(10);
string s1 = "string1";
int code = queue.InsertElement(new PriorityPair<string>(5, &s1));
string i = queue.PeekTop();
cout << "-------\n";
cout << i << endl;
这似乎有效,只要它确实正确插入了元素,但我不明白那对新的行为是否符合我的预期。当我运行代码时,我的优先级对的析构函数被调用了两次。这在调用函数 PeekTop 时特别发生。一次在队列的生命周期内,一次在队列超出范围并被销毁时。
这是上面代码的输出:
Code: 0
Destroy Pair for object :(string1): with priority :(5):
-------
string1
Destroy Queue with size: 1
Destroy Pair for object :(): with priority :(5):
第一个析构函数调用正确地显示了字符串及其值,但在第二个中我们可以看到字符串本身已经超出范围(这很好,也是预期的)。
【问题讨论】:
-
以下划线大写开头的名称保留用于实现;你的程序有未定义的行为。
-
这个
_Object;,以及所有以下划线和大写字符开头的标识符,或者包含两个连续下划线的标识符,在C++中被保留用于实现。您不得自己创建此类名称。像_Object这样的名称很可能会被实现使用。 -
请提供minimal reproducible example。
queue.InsertElement是什么?另外,我没有看到任何deletes 正在完成,它们是否被删除以创建更短的示例? -
@Caboose:不遵守规则的奇妙之处在于,你不一定会被告知你的错误,直到也许你已经出货了 100 万件并且诉讼开始进入。从这个意义上说,编程 C++ 比在学校参加数学考试要难得多:-(
-
为什么要加入
*((PriorityPair<T>)(*queueArray[0]))._Object?您的queueArray已经包含PriorityPair<T>类型的元素。由于我不知道它发生的确切原因,我不会发布答案,但演员本身会创建一个临时的。此外,由于缺少IsEmpty、maxSize和currentHeapSize,您的示例仍未完成,但这些添加很简单。
标签: c++ pointers return destructor