Stack vs Heap - *vector 中的对象是否应该声明为指针?
Stack vs Heap - Should objects inside *vector be declared as pointers?
如果我用这条线
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
- 如果我在堆栈中创建 MyObject 并将它们添加到向量中,它们将保留在堆栈中,对吗?
MyObject obj1;
vec->push_back(obj1);
所以如果它进入堆栈,那么添加到向量中的 MyObject 会在方法结束后消失吗? vector 里面有什么?垃圾?
我应该改用这个吗?:
std:vector* vec = new std::vector(100);
如果是这样,那么每个 MyObject 中的对象和原语呢?
它们是否也应该动态创建?
谢谢
std:vector
与任何其他标准库容器一样 将元素 复制到自身中,因此它拥有这些元素。因此,如果你有一个动态分配的std::vector
,你.push_back()
的元素将被复制到由std::vector
管理的内存中,因此它们将被复制到堆上。
作为旁注,在某些情况下 std::vector
可以 move
元素,如果这样做是安全的,但效果是一样的 - 最后,所有这些要素在 std::vector
的管辖范围内。
此外,请记住这
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
不将堆分配的对象存储到向量中。它只存储 MyObject 类型的指针。如果你想做类似的事情,请记住先创建对象,然后再使用它们。您可以使用类似以下的方法来做到这一点:
for (int i = 0; i < vec->size(); i++) {
vec->at(i) = new MyObject();
}
A std::vector<MyObject>
看起来像这样(实际上要复杂得多):
struct Vector {
MyObject* data;
int size;
}
如您所见,数据并不直接在向量对象中。 vector 总是为堆上的数据分配内存。以下是发生的情况:
- 你调用
.push_back
:向量将对象复制到它自己的数据块(它在堆上并由向量拥有)
- 您复制向量:复制的向量分配新内存并将现有向量中的所有数据复制到其中
如你所见,向量拥有他的数据。这意味着,如果你 push_back 一个对象进入它,它来自哪里并不重要,因为它被复制了。
如果你有一个 std::vector<MyObject>*
你有一个指向向量的指针。这个向量也拥有他的数据,但你只有一个指向它的指针。这意味着,您必须 delete
它恰好一次,否则您将遇到内存泄漏或崩溃。传递指向向量的指针是可以的,但需要一个 class 或“拥有”它的函数。 class/function 必须保证在使用指向它的指针时向量仍然存在。
第三种情况是std::vector<MyObject*>
。作为每一个矢量,这个也拥有他的数据。但这一次,数据只是一个指针。所以 vector 只拥有指针,而不拥有指针指向的对象。如果你这样做:
std::vector<MyObject*> getObjects() {
MyObject obj1("foo");
MyObject obj2("bar");
std::vector<MyObject*> vec;
vec.push_back(&obj1);
vec.push_back(&obj2);
return vec;
}
返回的向量仅包含垃圾,因为您只将地址保存到堆栈上的对象。这些对象在函数returns时被销毁,但vector中的指针仍然指向栈上的那个内存块。
如果我用这条线
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
- 如果我在堆栈中创建 MyObject 并将它们添加到向量中,它们将保留在堆栈中,对吗?
MyObject obj1; vec->push_back(obj1);
所以如果它进入堆栈,那么添加到向量中的 MyObject 会在方法结束后消失吗? vector 里面有什么?垃圾?
我应该改用这个吗?:
std:vector
* vec = new std::vector (100);
如果是这样,那么每个 MyObject 中的对象和原语呢? 它们是否也应该动态创建?
谢谢
std:vector
与任何其他标准库容器一样 将元素 复制到自身中,因此它拥有这些元素。因此,如果你有一个动态分配的std::vector
,你.push_back()
的元素将被复制到由std::vector
管理的内存中,因此它们将被复制到堆上。
作为旁注,在某些情况下 std::vector
可以 move
元素,如果这样做是安全的,但效果是一样的 - 最后,所有这些要素在 std::vector
的管辖范围内。
此外,请记住这
std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);
不将堆分配的对象存储到向量中。它只存储 MyObject 类型的指针。如果你想做类似的事情,请记住先创建对象,然后再使用它们。您可以使用类似以下的方法来做到这一点:
for (int i = 0; i < vec->size(); i++) {
vec->at(i) = new MyObject();
}
A std::vector<MyObject>
看起来像这样(实际上要复杂得多):
struct Vector {
MyObject* data;
int size;
}
如您所见,数据并不直接在向量对象中。 vector 总是为堆上的数据分配内存。以下是发生的情况:
- 你调用
.push_back
:向量将对象复制到它自己的数据块(它在堆上并由向量拥有) - 您复制向量:复制的向量分配新内存并将现有向量中的所有数据复制到其中
如你所见,向量拥有他的数据。这意味着,如果你 push_back 一个对象进入它,它来自哪里并不重要,因为它被复制了。
如果你有一个 std::vector<MyObject>*
你有一个指向向量的指针。这个向量也拥有他的数据,但你只有一个指向它的指针。这意味着,您必须 delete
它恰好一次,否则您将遇到内存泄漏或崩溃。传递指向向量的指针是可以的,但需要一个 class 或“拥有”它的函数。 class/function 必须保证在使用指向它的指针时向量仍然存在。
第三种情况是std::vector<MyObject*>
。作为每一个矢量,这个也拥有他的数据。但这一次,数据只是一个指针。所以 vector 只拥有指针,而不拥有指针指向的对象。如果你这样做:
std::vector<MyObject*> getObjects() {
MyObject obj1("foo");
MyObject obj2("bar");
std::vector<MyObject*> vec;
vec.push_back(&obj1);
vec.push_back(&obj2);
return vec;
}
返回的向量仅包含垃圾,因为您只将地址保存到堆栈上的对象。这些对象在函数returns时被销毁,但vector中的指针仍然指向栈上的那个内存块。