0

我提供了两种向我的集合添加元素的方法,一个是每个 const 引用,一个是每个指针。

void push_back(const value_type *val) {
    element *elem = new element(val);
    //...
}
void push_back(const value_type &val) {
    push_back(&val);
}

该类element将值作为指针保存。

class element {
private:
    const value_type *value;
public:
    element(const value_type *value):
    value(value) {
    } 

    ~element() {
        delete value;
    }

显然,当弹出元素或删除集合时,如果元素作为指针添加,则必须释放内存。但是,当元素不是手动分配并通过引用传递时,这会产生错误。

如果元素是在 push_back 时间动态分配的,除了额外存储之外,还有其他选择可以解决这个问题吗?

4

2 回答 2

1

只要保持一致并始终存储一个可以删除的指针。

void push_back(const value_type &val) {
    push_back(new value_type(val));
}
于 2013-09-04T21:47:57.707 回答
1

总的来说,这是一个有缺陷的设计。您可以通过不同的方式更改设计以实现您的需求。例如,马克的回答是一种直接的方法

话虽如此,这是使用您的设计的可能解决方案。再一次,我不推荐它,因为它依赖于编译器如何构建堆栈的内部结构,并且不能跨编译器/平台移植。

基本上,您可以通过将其与当前堆栈指针进行比较来~element()检查存储在其中的地址是在堆栈上还是在堆上。value如果存储在其中的地址value高于堆栈指针,则它在堆栈上并且不应被删除(假设堆栈的通常位置位于地址空间的顶部)。如果它小于堆栈指针 - 它在堆上。

说明地址关系的代码(GCC,x64 linux):

#include <iostream>

int main()
{
 int * heap_(new int(0));
 int stack_(0);
 void * rsp_(nullptr);

 asm("mov %%rsp, %0" : "=m" (rsp_));

 std::cout << "heap address\t: " << heap_ 
           << "\nstack address\t: " << &stack_ 
           << "\nstack pointer\t: " << rsp_ << std::endl;

 delete (heap_);

 return (0);
}

程序输出:

heap address    : 0xc52010
stack address   : 0x7fff528ffee4
stack pointer   : 0x7fff528ffee0

ideone.com 提供对 GCC 的访问权限,但使用 x86 版本 -esp注册而不是rsp. 必须更改代码(不可移植性)。

于 2013-09-04T23:17:15.270 回答