我想制作一个对象矢量,但我不想在堆上分配它们。我想将它们分配到堆栈内存中。但是我遇到了问题。
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))
,它会起作用。但是,我不希望将这些对象分配到需要手动管理内存的堆上。
答案 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(或移动)时都会复制。因此,如果您的对象很大,那不是一个好主意。
此外,在你的对象中,如果你最终有指针,使用智能指针也会对你有很大帮助。所以,无论如何,这是一个了解它们的好主意。