内存,在
C ++中,使用它总是很困难(
C的痛苦传统)...在这里,带有
std :: shared_ptr的 C ++ 11可以为我们提供帮助。
您可能已经猜到,如果这些原语没有问题,那么本文就不会是:)
让我们看一下以下关于
std :: shared_ptr的经典内存泄漏的示例:
#include <iostream> #include <memory> class Child; class Parent { public: Parent() { std::cout << "Parent()" << std::endl; } ~Parent() { std::cout << "~Parent()" << std::endl; } void createChild() { child_ptr_ = std::make_shared<Child>(); } std::shared_ptr<Child> getChild() { return child_ptr_; } private: std::shared_ptr<Child> child_ptr_; }; class Child { public: Child() { std::cout << "Child()" << std::endl; } ~Child() { std::cout << "~Child()" << std::endl; } void setParent(std::shared_ptr<Parent> parentPtr) { parent_ptr_ = parentPtr; } private: std::shared_ptr<Parent> parent_ptr_; }; int main() { auto parent = std::make_shared<Parent>(); parent->createChild(); parent->getChild()->setParent(parent); return 0; }
显然,我们不会看到对象析构函数的调用。 怎么处理呢?
std :: weak_ptr助我们
一臂之力 :
... class Child { ... void setParent(std::shared_ptr<Parent> parentPtr) { parent_ptr_ = parentPtr; } private: std::weak_ptr<Parent> parent_ptr_; }; ...
是的,它有助于解决问题。 但是,如果您具有更复杂的对象层次结构,并且很难理解谁应该执行
std :: weak_ptr ,谁应该执行
std :: shared_ptr ? 还是根本不想弄乱连接?
垃圾收集器是我们的一切!不,当然不是。 在C ++中,没有对Garbage Collector的本机支持,即使我们添加了它,我们也获得了Garbage Collector的间接费用,外加RAII中断。
我们该怎么办?
确定性垃圾收集器指针是一个指针,它跟踪来自
根对象的所有链接,并且一旦没有一个
根对象引用了我们的对象,它就会立即被删除。
其操作原理类似于
std :: shared_ptr (它跟踪
scope ),但也引用它的对象。
让我们在上一个示例中查看其操作原理:
#include <iostream> #include "gc_ptr.hpp" class Child; class Parent { public: Parent() { std::cout << "Parent()" << std::endl; } ~Parent() { std::cout << "~Parent()" << std::endl; } void createChild() { child_ptr_.create_object(); } memory::gc_ptr<Child> getChild() { return child_ptr_; } void connectToRoot(void * rootPtr) { child_ptr_.connectToRoot(rootPtr); } void disconnectFromRoot(bool isRoot, void * rootPtr) { child_ptr_.disconnectFromRoot(isRoot, rootPtr); } private: memory::gc_ptr<Child> child_ptr_; }; class Child { public: Child() { std::cout << "Child()" << std::endl; } ~Child() { std::cout << "~Child()" << std::endl; } void setParent(memory::gc_ptr<Parent> parentPtr) { parent_ptr_ = parentPtr; } void connectToRoot(void * rootPtr) { parent_ptr_.connectToRoot(rootPtr); } void disconnectFromRoot(bool isRoot, void * rootPtr) { parent_ptr_.disconnectFromRoot(isRoot, rootPtr); } private: memory::gc_ptr<Parent> parent_ptr_; }; int main() { memory::gc_ptr<Parent> parent; parent.create_object(); parent->createChild(); parent->getChild()->setParent(parent); return 0; }
如您所见,代码已经增加了一些,但这是全自动删除对象需要付出的代价。 可以看出,已经添加了附加的
connectToRoot和
disconnectFromRoot方法。 当然,一直用双手写作会非常困难,因此我打算在使用
gc_ptr的类中为这些方法生成一个小型生成器(因为我们看到这些方法遵循
零开销原则,因此我们不为不使用的东西付费,如果我们使用-则成本不超过我们亲手写的成本)。
gc_ptr.hpp库
是线程安全的,它不会为垃圾回收创建任何其他线程,一切都在构造函数,析构函数和赋值运算符中完成,因此,如果我们覆盖对象并且不再有
根对象引用它,则返回为我们的对象分配的内存。
感谢您的关注!