我正在C中实现一个通用堆栈用于学习目的。这是它的流行功能:
void* StackPop(Stack *s) {
assert(s != NULL);
assert(s->logicalLen > 0); // there must be at least on element
void *object = (char*) s->elems + (s->logicalLen--) * s->elemSize; // decrement logical length
// on the fly
return object;
}
在这种情况下(StackPop)我很清楚我必须将顶部对象的所有权转移给调用者。因此返回一个通用指针很好,因为调用者想要决定如何处理该对象。 另一方面,我想写一个StackTop()函数来返回顶部元素。这对我来说是如此不确定:我知道两个函数应该非常相似,不同之处在于我不应该减小堆栈的大小或返回指针,因为我不希望客户端修改它。如何仅传递顶级元素的副本呢?接受一个通用指针作为参数我唯一的选择并深入复制到该地址?
void StackPop(void *target) {
// make a deep copy into target address with memcopy or whatever?
}
有更好的方法吗?
答案 0 :(得分:1)
我知道这两个功能应该非常相似......
谁说的?
您正在设计堆栈,因此您可以自由定义使用堆栈的所有规则。例如,您允许跳过对NULL指针的所有检查,只需在文档中写入使用NULL指针调用函数xxx
会导致未定义的行为。最后,它取决于你想要的堆栈 - 高性能,安全使用,易于使用等。
这同样适用于StackPop
和StackTop
函数。你可以自由设定规则。
对我来说,StackPop
似乎在逻辑上是错误的。通过递减logicalLen
返回指向逻辑上已释放的内存区域的指针并不是我所期望的。但是你可以在文档中写下StackPop
返回的指针在下一个StackPush
时变为无效。 (在C ++中,一些容器对迭代器/指针有这样的限制。)
同样适用于StackTop
- 您只需返回指向顶部元素的指针,并声明它仅在下一个StackPop
之前有效。
这是你的设计,你的规则。
我宁愿这样做:
int push(stack* s, void* o)
{
// memcpy contents of o to next free location
// increment number of elements held
}
int top(stack* s, void* o)
{
// memcpy top element to o
}
int pop(stack* s)
{
// decrement number of elements held
}
在所有三种情况下,int
用于返回错误值。
为了提高性能,您可以提供一项功能,例如: ptop
返回指向顶部元素的指针(仅对下一个pop有效)。
关于deep copy
:
您无法在通用堆栈中执行深层复制。如果用户在堆栈中放入有指针的内容,则用户必须自己处理。