[英]C++ Smart Pointers in a Vector container
I wrote the classic Shape Polymorphism code, but a little bit different because I'm using a Vector container and smart pointers. 我编写了经典的Shape Polymorphism代码,但有点不同,因为我使用的是Vector容器和智能指针。
I am not a C++ expert, and I would like to know the following: 我不是C ++专家,我想知道以下内容:
shapes.clear()
, is there going to be a memory leak? shapes.clear()
,是否会出现内存泄漏? Code: 码:
#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;
}
Thank you :) 谢谢 :)
Your code doesn't contain a memory leak. 您的代码不包含内存泄漏。 So your first point is fine.
所以你的第一点很好。
No, if you don't call shapes.clear()
, there will not be a memory leak since std::vector
's destructor cleans up the container. 不,如果你不调用
shapes.clear()
,就不会有内存泄漏,因为std::vector
的析构函数会清理容器。
I don't know a specific rule about using shared pointers in a container so I'll skip on your third question. 我不知道在容器中使用共享指针的具体规则,所以我将跳过你的第三个问题。
However, I can offer an improvement for creating std::shared_ptr
s: 但是,我可以为创建
std::shared_ptr
提供改进:
When you create a shared pointer using its constructor, ie shared_ptr<T>(new T());
使用其构造函数创建共享指针时,即
shared_ptr<T>(new T());
, the control block or the structure that holds bookkeeping information about that resource, is created separately from the object it points to. , 控制块或保存有关该资源的簿记信息的结构是与它指向的对象分开创建的。 This might cause cache misses a lot.
这可能会导致缓存丢失很多。 However, if you create a
shared_ptr
by using std::make_shared
, the control block is allocated with the object you want, therefore, by keeping them together, you can at least mitigate the cost of cache misses: std::make_shared<T>();
但是,如果使用
std::make_shared
创建shared_ptr
,则控制块将分配您想要的对象,因此,通过将它们保持在一起,您至少可以降低缓存未命中的成本: std::make_shared<T>();
. 。 For example:
std::make_shared<Circle>(3)
is equivalent to writing std::shared_ptr<Shape>(new Circle(3))
, but usually better. 例如:
std::make_shared<Circle>(3)
相当于编写std::shared_ptr<Shape>(new Circle(3))
,但通常更好。
1) I don't see a memory leak here. 1)我在这里看不到内存泄漏。 However there is a potential to getting one sooner or later: your shape destructor is not virtual .
然而,迟早有可能获得一个: 你的形状析构函数不是虚拟的 。 This means that shapes are always destroyed using the base destructor, instead of the right destructor.
这意味着总是使用基础析构函数而不是正确的析构函数销毁形状。 Ie if one of your derived shapes would one day allocate memory, it's destructor that would have to release it wouldn't be called.
也就是说,如果你的某个派生形状有一天会分配内存,那么它的析构函数将不会被调用。
2) Nothing will happen: if you don't do a clear()
, shapes will get destroyed anyway when main()
is left, causing its contend to get destroyed. 2)什么都不会发生:如果你没有做一个
clear()
,当main()
离开时,形状会被破坏,导致它的竞争被破坏。
3) Maybe, but this one is already very good. 3)也许,但这个已经非常好了。
No, there won't be a memory leak, which is (part of) the entire point of smart pointers. 不,不存在内存泄漏,这是智能指针的整个点(部分)。 When the
vector
falls out of scope, it calls the destructor on all of its elements. 当
vector
超出范围时,它会在其所有元素上调用析构函数。 In this case, calling the destructor on the shared_ptr<Shape>
will cause it's internal shared reference count to hit 0
and will thus destroy the Shape
object. 在这种情况下,在
shared_ptr<Shape>
上调用析构函数将导致其内部共享引用计数达到0
并因此将销毁Shape
对象。
std::shared_ptr
destroys the elements properly. std::shared_ptr
也会正确地破坏元素。 (you should add it anyway though - sooner or later someone will hit this issue, as std::unique_ptr
won't handle this case) std::unique_ptr
不会处理这种情况) .clear()
- the destructor of std::vector
destroys all the elements, and the shared pointers destroys the element owned if they're the only owner. .clear()
- std::vector
的析构函数会破坏所有元素,如果共享指针是唯一的所有者,则共享指针会破坏所拥有的元素。 std::unique_ptr
instead, but only if you have a virtual destructor in Shape
. std::unique_ptr
,但std::unique_ptr
是您在Shape
有虚拟析构函数。 You should also use std::make_shared
and std::make_unique
(C++14) wherever you can to avoid a tricky issue with sequence points and throwing constructors: in essence f(std::unique_ptr<ConstructorAlwaysThrows>(new ConstructorAlwaysThrows()), std::unique_ptr<Foo>(new Foo()));
std::make_shared
和std::make_unique
(C ++ 14)来避免序列点和抛出构造函数的棘手问题:本质上f(std::unique_ptr<ConstructorAlwaysThrows>(new ConstructorAlwaysThrows()), std::unique_ptr<Foo>(new Foo()));
will leak memory, or not, depending on how the compiler does sequencing. Is there any memory leak?
有内存泄漏吗?
No, you are calling the destructor of shared_ptr
here. 不,你在这里调用
shared_ptr
的析构函数。
If I don't call shapes.clear(), is there going to be a memory leak?
如果我不调用shapes.clear(),是否会出现内存泄漏?
It depends, if your vector
lives then all of its contents will live, if the vector
dies then it will kill its contents automatically. 这取决于,如果你的
vector
存在,那么它的所有内容都将存在,如果vector
死亡,那么它将自动杀死它的内容。
Is there a better way to use smart pointers and containers?
有没有更好的方法来使用智能指针和容器?
make_shared
can be used to avoid problems if the new
throws an exception by ensuring that the shared_ptr
calls its destructor to delete the memory. 如果
new
抛出异常, make_shared
可用于避免问题,方法是确保shared_ptr
调用其析构函数来删除内存。 However that would require a conversion from shared_ptr<Rectangle>
to shared_ptr<Shape>
which is automatic if annoying (it involves copying the shared_ptr
and deleting the original). 但是,这需要从
shared_ptr<Rectangle>
转换为shared_ptr<Shape>
,如果烦人的话,它会自动转换(它涉及复制shared_ptr
并删除原始内容)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.