堆栈内存中对象的向量
Vector of objects in 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循环迭代后超出作用域后删除了自己。
现在,我知道你可以在每次迭代中只做v.push_back(new Object(i))
,这是可行的。但是,我不希望将这些对象分配到需要手动管理内存的堆上。
你基本上是正确的,"对象在超出作用域后[被销毁]"。打印的内容也会让人困惑。根据编译器在循环内分配具有"自动存储持续时间"的变量的方式,堆栈变量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>
将适当地管理你的对象生命周期,当向量本身超出作用域时销毁对象。但是对象实际上是存储在自由存储区中。
下面是ideone在编译和运行object向量时的输出:
0x8e66008
0x8e6601c
0x8e66030
0x8e66034
0x8e66050
如果你真的不想在堆栈上分配它们,而只是想管理内存,你真的应该花几个小时来填补一些知识空白。
特别是,掌握大量关于RAII的知识对于有效地使用c++和c++ 11是至关重要的。我强烈推荐《c++语言参考》第4版。第四版很重要,因为它与第三版非常不同。在其中,它将向您展示可能想要使用std::vector<std::unique_ptr>
来解决这个特定问题,或者使Object
本身成为一个托管对象(实现移动语义)。
删除的是向量,而不是对象。
下面的操作意味着将指针保存在向量v
中:
std::vector<Object*> v;
你可以这样做:
std::vector<Object> v;
在这种情况下,你得到许多对象,但然后你得到你的对象的副本,有时要么是不可能的,要么不是你想要的东西(虽然新版本的c++编译器可以做一个移动而不是复制,但我不认为这会在这种情况下工作…)
如果你想分配对象然后自动删除,另一种方法是使用智能指针。
#include <memory>
std::vector<std::shared_ptr<Object> > v;
在这种情况下,对象由您分配,并在删除vector时释放。
然而,你的问题是你在堆栈上初始化对象,并将堆栈指针赋值给vector。我想象一下,你的打印显示你的指针总是相同的。这意味着之前的对象被销毁,并在每次迭代时创建一个新对象。所以我将替换这些行:
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)。但是通过这种方式,你不需要管理内存,并且你有好的指针。
如果你更喜欢对象本身的解决方案,它将是这样的:
std::vector<Object> v;
Object o(i);
v.push_back(o);
这样可以避免堆,但是,每次push_back(或移动)时都会生成副本。所以如果你的对象很大,那就不是个好主意了。
同样,在你的对象中,如果你最终使用指针,使用智能指针也会对你有很大的帮助。这是了解它们的好方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 迭代时从向量和内存中删除对象
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 如何创建从同一类继承的不同对象的向量
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 从多个源构造一个对象,包括一个对象向量
- 在C 中,是否有可能在不兼容类型的std ::向量对象之间传输不同类型的缓冲区
- 将向量对象存储在共享指针投掷错误中
- E0312,C2664尝试将向量对象作为函数参数传递时错误
- 相对于向量对象的两个成员,找到两个向量的相交的有效方法
- 将数据从文件读取到向量对象
- C 向量对象访问
- 向量对象声明后的括号是什么意思
- 2向量对象指向相同的分配内存
- 如何返回向量对象
- 传递单个或向量对象时没有重载函数的实例
- 指向数组和向量对象的指针
- 向量对象库,可以存储其他对象类型的对象
- 如何从另一个向量/对象集构造新的向量/指针集