【问题标题】:Creating c++ vector of pointers创建 C++ 指针向量
【发布时间】:2013-11-23 05:07:11
【问题描述】:

在我的 C++ 代码中,我有一个类 Object,它配备了一个 int 类型的 id 字段。现在我想创建一个 Object* 类型的指针向量。首先我尝试了

vector<Object*> v;

for(int id=0; id<n; id++) {
    Object ob = Object(id);
    v.push_back(&ob);
}

但这失败了,因为这里相同的地址只是重复了 n 次。如果我使用 new 运算符,我会得到我想要的,但我想避免动态内存分配。然后我认为我需要以某种方式在 for 循环之前声明 n 个不同的指针。直接的方法是声明一个数组,所以我这样做了:

vector<Object*> v;
Object ar[n];

for(int i=0; i<n; i++) {
    ar[i] = Object(i);
}

for(int i=0; i<n; i++) {
    v.push_back(ar+i);
}

如果我这样做,是否还有可能发生内存泄漏?在我看来,通过数组声明也有点笨拙。有没有其他方法可以创建指针向量但避免手动内存管理?

编辑:为什么我需要指针而不是普通对象?

好吧,我对原来的实际情况进行了一些修改,因为我认为这样我可以用最简单的形式表示问题。无论如何,我仍然认为可以在不知道为什么需要指针向量的情况下回答这个问题。

其实我有

Class A {
protected:
    vector<Superobject*> vec;
...
};

Class B: public A {...};

Class Superobject {
protected:
    int id;
...
}

Class Object: public Superobject {...}

在派生类B 中,我想用Object 类型的对象填充成员字段vec。如果超类不使用指针,我会遇到对象切片问题。所以在B类的构造函数中,我想将vec初始化为Object*类型的指针向量。

EDIT2

是的,在我看来动态分配是合理的选择,而使用数组的想法是个坏主意。当数组超出范围时,事情就会出错,因为向量中的指针指向的内存位置不再一定包含对象。

在我有的 B 类的构造函数中

B(int n) {
    vector<Object*> vec;
    Object ar[n];

    for(int id=0; id<n; id++) {
        ar[id] = Object(id);
    }

    for(int id=0; id<n; id++) {
        v.push_back(ar+id);
    }
 }

这在 B 类的对象中引起了非常奇怪的行为。

【问题讨论】:

  • 如果您不想要动态内存分配,那么为什么要使用指针?您也可以使用 Object 数组。
  • 为什么要首先存储指针?
  • 第二种方法的问题是它不是合法的 C++。 Object ar[n]; 是不合法的,除非 n 是一个常数。此外,由于根据您的编辑,您有一个类层次结构,但使用Object ar[n]; 您只有对象,而不是超对象。顺便说一句,您的第一种方法也是错误的,因为您要存储已被破坏的对象的地址。我只会使用动态内存分配。

标签: c++ pointers vector


【解决方案1】:

在这个循环中:

for(int id=0; id<n; id++) {
    Object ob = Object(id);
    v.push_back(&ob);
}

您正在堆栈上创建 n 次 Object 实例。在每次迭代中,都会创建和删除元素。您可以简单地使用它来避免这种情况:

for(int id=0; id<n; id++) {
    Object* ob = new Object(id);
    v.push_back(ob);
}

感谢每个新元素都存在于堆上而不是堆栈上。尝试在类 Object 构造函数中添加类似的内容:

std::cout<<"Object ctor()\n";

在析构函数中也一样:

std::cout<<"Object dtor()\n";

如果您不想使用@woolstar 编写的“新”尝试原因来创建这些对象

【讨论】:

    【解决方案2】:

    您关于内存泄漏的问题让我觉得您担心这些对象的生命周期和清理。我最初提出了shared_ptr 包装器,但是C++11 给了我们unique_ptr,而C++14 填补了缺失的make_unique。所以我们能做的就是:

    vector<unique_ptr<SuperObject>> v ;
    

    您使用完美的转发和可变参数模板的美妙之处创建,

    v.push_back( make_unique<Object>( ... ) ) ;
    

    是的,您将不得不忍受一些堆分配,但是当v 消失时,一切都会被清理。

    有人提出了一个 boost 库 ptr_container,但这不仅需要为您的项目添加 boost,还需要让所有未来的读者了解这个 ptr_container 是什么以及做什么。

    【讨论】:

    【解决方案3】:

    不,您的版本没有内存泄漏。当程序离开您的范围时,向量以及数组都会被销毁。关于第二个问题:为什么不直接将对象直接存储在向量中?

    vector<Object> v;
    
    for(int i = 0; i < n; i++)
    {
        Object obj = Object(i);
        v.push_back(obj);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 2012-06-13
      • 1970-01-01
      相关资源
      最近更新 更多