堆栈与堆 - 是否应该将 *vector 内的对象声明为指针?

问题描述

如果我使用这条线

void merge3(string MFile3)
{

string file1name,file2name,file3name,outfilename,word1,word2,word3;
cout << "Enter name of first file: ";
cin >> file1name;
cout << "Enter name of second file: ";
cin >> file2name;
cout << "Enter name of third file: ";
cin >> file3name;
cout << "Enter name of output file: ";
cin >> outfilename;


ofstream inFileFour(outfilename.c_str());

ifstream inFileOne(file1name.c_str());
while (inFileOne >> word1) {
    ifstream inFileTwo(file2name.c_str());
    

    while (inFileTwo >> word2) {

        ifstream inFileThree(file2name.c_str());
    
        while (inFileThree >> word3) {
            

            inFileFour << word1 << word2 << word3 << endl;

        }
        inFileThree.close();
    }

    inFileTwo.close();
    
}
inFileOne.close();
inFileFour.close();

}
  • 如果我在堆栈中创建 MyObject 并将它们添加到向量中,它们会保留在堆栈中,对吗?
std:vector<MyObject>* vec = new std::vector<MyObject>(100);
  • 因此,如果它进入堆栈,那么在方法结束后,添加到向量中的 MyObject 将消失?我在向量中会有什么比?垃圾

  • 我应该用这个代替吗?:

    std:vector* vec = new std::vector(100);

如果是这样,那么每个 MyObject 中的对象和基元呢? 它们也应该动态创建吗?

谢谢

解决方法

与任何其他标准库容器一样,std:vector 将元素复制到自身中,因此它拥有它们。因此,如果您有一个动态分配的 std::vector,您 .push_back() 的元素将被复制到由 std::vector 管理的内存中,因此它们将被复制到堆中。

作为旁注,在某些情况下,std::vector 可能是 move 元素,如果这样做是安全的,但效果是一样的 - 最后,所有元素都在std::vector 的管辖权。

,

std::vector<MyObject> 看起来像这样(实际上它要复杂得多):

struct Vector {
    MyObject* data;
    int size;
}

如您所见,数据并不直接位于矢量对象内部。向量总是为堆上的数据分配内存。以下是发生的情况:

  • 你调用.push_back:向量将对象复制到它自己的数据块(它在堆上并由向量拥有)
  • 你复制向量:复制的向量分配新的内存并将所有数据从现有向量复制到其中

如您所见,向量拥有他的数据。这意味着,如果你将一个对象推回其中,它来自哪里并不重要,因为它被复制了。

如果你有一个 std::vector<MyObject>* 你有一个指向向量的指针。这个向量也拥有他的数据,但你只有一个指向它的指针。这意味着,您必须delete 只执行一次,否则会出现内存泄漏或崩溃。传递指向向量的指针是可以的,但需要一个“拥有”它的类或函数。这个类/函数必须保证向量在使用指针时仍然存在。

第三种情况是 std::vector<MyObject*>。与每个向量一样,这个向量也拥有他的数据。但这一次,数据只是一个指针。所以向量只拥有指针,而不拥有指针指向的对象。如果你这样做:

std::vector<MyObject*> getObjects() {
    MyObject obj1("foo");
    MyObject obj2("bar");
    std::vector<MyObject*> vec;
    vec.push_back(&obj1);
    vec.push_back(&obj2);
    return vec;
}

返回的向量只包含垃圾,因为您只将堆栈上的对象的地址保存到它。这些对象在函数返回时被销毁,但向量中的指针仍然指向堆栈上的那个内存块。

,

另外,请记住这一点

std:vector* vec = new std::vector(100);

不将堆分配的对象存储到向量中。它只存储 MyObject 类型的指针。如果你想做这样的事情,记得先创建对象,然后再使用它们。您可以使用以下内容来做到这一点:

  for (int i = 0; i < vec->size(); i++) {
    vec->at(i) = new MyObject();
  }