C++ 处理已分配和堆栈内存

C++ 处理已分配和堆栈内存,c++,C++,我提供了两种向集合中添加元素的方法,一种是每个常量引用一次,另一种是每个指针一次 void push_back(const value_type *val) { element *elem = new element(val); //... } void push_back(const value_type &val) { push_back(&val); } 元素类将值作为指针保存 class element { private: const

我提供了两种向集合中添加元素的方法,一种是每个常量引用一次,另一种是每个指针一次

void push_back(const value_type *val) {
    element *elem = new element(val);
    //...
}
void push_back(const value_type &val) {
    push_back(&val);
}
元素
类将值作为指针保存

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

    ~element() {
        delete value;
    }
显然,当弹出元素或删除集合时,如果元素作为指针添加,则必须释放内存。 但是,如果没有手动分配元素并通过引用传递,则会产生错误


如果元素是在推送时间动态分配的,那么除了额外存储之外,还有其他解决此问题的方法吗?

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

void push_back(const value_type &val) {
    push_back(new value_type(val));
}

总的来说,这是一个有缺陷的设计。你可以通过不同的方式改变你的设计来达到你的需要。例如,马克的回答是一种直截了当的方式

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

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

用于说明地址关系的代码(GCC、x64 linux):


ideone.com允许访问GCC,但使用x86版本-
esp
寄存器,而不是
rsp
。(不可移植)。

如果我正确理解了代码,
push\u back(const-value\u-type&)
只是自找麻烦。如果我这样做呢
{value_type a;collection.push_back(a);}
一旦
a
在作用域的末尾被销毁,则
collection
对象将最终持有一个悬空指针。这是一个糟糕的设计,因为这个问题已经存在,我甚至没有谈到“无论对象是在堆栈上还是在堆上,都要做非常不同的事情”这件事。@Macmade我需要有多个列表指向相同的元素,我需要动态地合并和分割它们。我同意你。但这似乎是另一种情况。您似乎面临的真正问题是必须维护同一组项目的不同列表,这是专门为之设计的。当您在同一容器中混合使用分配习惯用法时,会发生这种情况。只是不要这么做。@jev不会总是为他的代码返回“yes,pointer”,因为他正在推送通过引用传入的堆栈局部变量的地址吗?
#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