Vector容器中的C++智能指针

Emm*_*oya 4 c++ polymorphism smart-pointers stdvector

我编写了经典的Shape Polymorphism代码,但有点不同,因为我使用的是Vector容器和智能指针.

我不是C++专家,我想知道以下内容:

  1. 有内存泄漏吗?
  2. 如果我不打电话shapes.clear(),会不会有内存泄漏?
  3. 有没有更好的方法来使用智能指针和容器?

码:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class Shape {
  public:
    virtual float getArea() = 0;
    virtual ~Shape() {}
};

class Rectangle : public Shape {
  public:
    Rectangle(float w, float h) : width(w), height(h) {}

    float getArea() {
      return width * height;
    }
  private:
    float width;
    float height;
};

class Circle : public Shape {
  public:
    Circle(float r) : radius(r) {}

    float getArea() {
      return 3.141592653589793238462643383279502884 * radius * radius;
    }
  private:
    float radius;
};

void printShapeAreas(vector<shared_ptr<Shape>> &shapes) {
  for(int i = 0; i < shapes.size(); i++) {
    cout << shapes[i]->getArea() << endl;
  }
}

int main(int argc, char** argv) {
  vector<shared_ptr<Shape>> shapes;
  //this works, but you told me that is better to use make_shared
  //=============================================================
  //shapes.push_back(shared_ptr<Shape>(new Rectangle(10, 2)));
  //shapes.push_back(shared_ptr<Shape>(new Rectangle(10, 3)));
  //shapes.push_back(shared_ptr<Shape>(new Circle(2)));
  //shapes.push_back(shared_ptr<Shape>(new Circle(3)));
  //better
  //======
  shapes.push_back(std::make_shared<Rectangle>(10, 2));
  shapes.push_back(std::make_shared<Rectangle>(10, 3));
  shapes.push_back(std::make_shared<Circle>(2));
  shapes.push_back(std::make_shared<Circle>(3));
  printShapeAreas(shapes);
  shapes.clear();//If I don't call shapes.clear(), is there going to be a memory leak?
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢 :)

Fat*_*KIR 7

您的代码不包含内存泄漏.所以你的第一点很好.

不,如果你不打电话shapes.clear(),就不会有内存泄漏,因为std::vector析构函数会清理容器.

我不知道在容器中使用共享指针的具体规则,所以我将跳过你的第三个问题.

但是,我可以为创建std::shared_ptrs 提供改进:

当使用它的构造,即,创建共享指针shared_ptr<T>(new T());,所述控制块或保持有关该资源的记录信息的结构中,分别从它指向的对象创建的.这可能会导致缓存丢失很多.但是,如果你shared_ptr通过使用创建一个std::make_shared控制块,那么控制块就会分配你想要的对象,因此,通过将它们保持在一起,你至少可以降低缓存未命中的成本:std::make_shared<T>();.例如:std::make_shared<Circle>(3)相当于写作std::shared_ptr<Shape>(new Circle(3)),但通常更好.

  • 另外,如果您的构造函数抛出异常,那么它将被make_shared删除,但不会被shared_ptr构造函数删除,因为在后一种情况下,永远不会调用该构造函数。 (2认同)

Chr*_*phe 5

1) 我在这里没有看到内存泄漏。然而,迟早有可能得到一个: 你的形状析构函数不是 virtual。这意味着总是使用基础析构函数而不是正确的析构函数来销毁形状。即,如果您的派生形状之一有一天会分配内存,则必须释放它的析构函数将不会被调用。

2) 什么都不会发生:如果你不做 a clear()main()剩下的形状无论如何都会被破坏,导致它的竞争被破坏。

3) 也许吧,但这个已经很好了。