对象传染媒介在堆内存的

时间:2014-07-06 02:57:14

标签: c++ vector stack-memory

我想制作一个对象矢量,但我不想在堆上分配它们。我想将它们分配到堆栈内存中。但是我遇到了问题。

struct Object { int x; Object(int x) { this->x = x; } };

int main() {
    std::vector<Object*> v;

    for (int i = 0; i < 5; i++) {
        Object o (i);
        v.push_back(&o);
        std::cout << &o << std::endl; // keeps printing the same mem address...
                                      // ...implying that these are all the same object
    }
}

我怀疑在for-loop的每次迭代之后,对象在超出范围后会自行删除。

现在,我知道你可以为每次迭代做v.push_back(new Object(i)),它会起作用。但是,我不希望将这些对象分配到需要手动管理内存的堆上。

3 个答案:

答案 0 :(得分:1)

基本上正确的是“超出范围后对象被[被破坏]”。由于你正在打印什么,它也令人困惑。根据编译器如何在循环中使用“自动存储持续时间”分配变量,堆栈变量Object o始终具有相同的地址。

std::vector<Object*> v;
for (int i = 0; i < 5; i++) {
    Object o (i);
    v.push_back(&o);
    // Variable o still exists on the stack
    std::cout << &o << std::endl; // Prints the address of the automatic variable 'o'
}

// At this point, no objects exist; they all went out of scope
// every pointer in v is invalid, pointing to the "ghost" of a destoryed object.

我认为您正在寻找的更简单的方法是简单地创建一个对象向量。

std::vector<Object> v;

for (int i = 0; i < 5; i++) {
    v.push_back(Object(i));
    std::cout << &(v.back()) << std::endl; // Prints the address of the Object just added
}

那就是说,你应该明白std::vector<Object>会正确管理你的对象生命周期,当向量本身超出范围时会破坏对象。但是对象实际上存储在免费商店中。这没关系。

使用对象向量编译和运行时,这是output from ideone

0x8e66008
0x8e6601c
0x8e66030
0x8e66034
0x8e66050

答案 1 :(得分:0)

如果你真的不想在堆栈上分配它们,而只是想管理内存,你真的应该花几个小时来填补一些知识空白。

特别是,获取有关RAII的大量知识对于有效使用C ++和C ++ 11至关重要。我强烈推荐The C++ Language Reference, 4th Edition。第4版非常重要,因为它与第3版非常不同。

在其中,它会向您显示可能希望对此特定问题使用std::vector<std::unique_ptr>,或者使Object成为托管对象本身(已实现移动语义)。

答案 2 :(得分:-1)

删除了矢量,而不是对象。

以下表示您在向量v中保存指针:

std::vector<Object*> v;

你可以这样做:

std::vector<Object> v;

在这种情况下你得到很多对象,但是你得到的对象副本有时候是不可能的或不是你想要的东西(尽管较新版本的C ++编译器可以移动而不是副本,但是我不要以为在这种情况下会起作用......)

如果您想要分配然后自动删除对象,另一种方法是使用智能指针。

#include <memory>
std::vector<std::shared_ptr<Object> > v;

在这种情况下,对象由您分配,并在向量被删除时释放。

但是,您的问题是您初始化堆栈上的对象并将该堆栈指针指定给您的向量。我会想象你的打印显示指针始终是相同的......意味着前一个对象被破坏,每次迭代都会创建一个新对象。

所以我会替换这些行:

std::vector<Object*> v;

    Object o (i);
    v.push_back(&o);

通过以下方式:

std::vector<std::shared_ptr<Object> > v;

    std::shared<Object> o(new Object(i));
    v.push_back(o);

如果您对共享指针一无所知,我建议您阅读它们。每当您使用new分配对象时,它都非常有用。还有一些陷阱与所谓的循环引用(即检查weak_ptr)。但是通过这种方式,你不必管理内存,而且你有很好的指针。

如果您更喜欢具有Object的解决方案,它将是这样的:

std::vector<Object> v;

    Object o(i);
    v.push_back(o);

这样就可以避免堆,但是每次push_back(或移动)时都会复制。因此,如果您的对象很大,那不是一个好主意。

此外,在你的对象中,如果你最终有指针,使用智能指针也会对你有很大帮助。所以,无论如何,这是一个了解它们的好主意。