如何正确地推回然后循环遍历位于堆中的对象的向量?

How to properly push back and then loop through vector of objects located in the heap?

我有以下 class:

#include <iostream>
#include <math.h>
#include <vector>
class minimal
{
private:
    int x;
    int y;
public:
    minimal(int x = NAN, int y = NAN)  // default constructor
    {
        this->x = x;
        this->y = y;
    }
    ~minimal(){}
    void setvals(int xin, int yin)
    {
        this->x = xin;
        this->y = yin;
    }
    int getx() {return this->x;}
};
int main() {
    // goal: create a vector of type minimal to be located in the heap
    std::vector<minimal*> vectinheap;

    minimal * min_ptr = new minimal;
    for (int i = 0; i < 4; ++i)
    {
        min_ptr->setvals(i, -i);
        vectinheap.push_back(min_ptr);  // send a local copy to vectinheap?
    }
    delete min_ptr;  // free the heap
    min_ptr = nullptr;  // free dangling pointer
    // now how to iterate through vect in heap.. ?
    return 0;
}

由此产生了几个问题:

  1. 当我说 vectinheap.push_back(min_ptr) 是要使向量中的每个值最终都指向同一个实例,还是会像我想要的那样附加当前实例?
  2. 加载位于堆中的向量后,如何通过索引向量来遍历并访问每个实例?
  1. 您最好将 std::vector<minimal*> vectinheap; 重命名为 vect_of_ptr,因为您的向量不在堆中。
  2. When I say vectinheap.push_back(min_ptr) is that going to make each value in the vector be pointing to the same instance in the end, or will it append the current instance like I am wanting?

您正在将指向堆上分配的同一个 minimal 对象的指针推送到向量 vectinheap

  1. After loading the vector located in the heap, how can I then iterate through and access each instance by indexing the vector?

你做到了:

for(const auto& item: vectinheap)
{
    //item is a pointer, you can get your object by dereference it using *
}

注意:你只在堆中创建了一个minimal的对象,但是你将四个指向它的指针(同一个对象)压入了你的vector。并且您已通过 delete min_ptr; 删除了该对象。循环遍历向量并取消引用其中的指针将变为 undefined.

您应该通过将 minimal * min_ptr = new minimal; 移动到您的 for 循环中来修复它。并且 当您循环浏览 vectinheap.

时,不要忘记删除它们

我假设您有 C# 或 Java 背景? (因此尝试新的一切的原因?)。在 C++ 中执行此操作的方式如下:

int main() {
    // store a vector of minimal structs
    std::vector<minimal> vectinheap;

    int n = 4;
    for (int i = 0; i < n; ++i)
    {
        int xlocal = i;  // set dummy vals for filling vectinheap
        int ylocal = -i;

        // emplace_back will construct a new item at the end of the vector
        vectinheap.emplace_back(xlocal, ylocal);
    }


    // and now to iterate (range based for loop - best method)
    for(auto& value : vectinheap)
    {
      std::cout << value.getx() << ' ' <<  value.gety() << std::endl;
    }

    // the less good way using iterators
    for(auto it = vectinheap.begin(); it != vectinheap.end(); ++it)
    {
      std::cout << it->getx() << ' ' <<  it->gety() << std::endl;
    }

    // and using indices if you really must
    for(size_t i = 0; i < vectinheap.size(); ++i)
    {
      std::cout << vectinheap[i].getx() << ' ' <<  vectinheap[i].gety() << std::endl;
    }

}

然而,使用push_back/emplace_back构造一个简单的POD数组是一种非常低效的方法。通常最好先分配一次,然后简单地填充数据。这样你就不会在每次循环迭代时都问 "can I append one more item to this array without resizing it?" 这个问题。

    int n = 4;

    // allocate enough memory for 'n' structs
    std::vector<minimal> vectinheap(n);

    for (int i = 0; i < n; ++i)
    {
        int xlocal = i;  // set dummy vals for filling vectinheap
        int ylocal = -i;

        // just use the array brackets to access
        vectinheap[i].setvals(xlocal, ylocal);
    }