我目前正在尝试找出如何shared_ptr
在C++ API中正确使用C++ 11 的功能.我需要它的主要区域是容器类(例如场景图中的节点,例如可能包含子节点列表和父节点的引用以及类似的东西).创建节点的副本不是一个选项,使用引用或指针是痛苦的,因为没有人真正知道谁负责破坏节点(当有人破坏仍被其他节点引用的节点时,程序将崩溃).
所以我认为shared_ptr
在这里使用可能是一个好主意.让我们看一下下面的简化示例(它演示了一个必须连接到父节点的子节点):
#include <memory>
#include <iostream>
using namespace std;
class Parent {};
class Child {
private:
shared_ptr<Parent> parent;
public:
Child(const shared_ptr<Parent>& parent) : parent(parent) {}
Parent& getParent() { return *parent.get(); }
};
int main() {
// Create parent
shared_ptr<Parent> parent(new Parent());
// Create child for the parent
Child child(parent);
// Some other code may need to get the parent from the child again like this:
Parent& p = child.getParent();
...
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此API强制用户使用a shared_ptr
来创建子级和父级之间的实际连接.但在其他方法中,我想要一个更简单的API,这就是为什么该getParent()
方法返回对父项的引用而不是shared_ptr
.
我的第一个问题是:这是正确用法shared_ptr
吗?还是有改进的余地?
我的第二个问题是:我如何对空指针做出正确的反应?因为该getParent
方法返回一个引用,用户可能认为它永远不会返回NULL.但这是错误的,因为当有人传递包含指向构造函数的空指针的共享指针时,它将返回NULL.其实我不想要空指针.必须始终设置父级.我该如何妥善处理?通过手动检查构造函数中的共享指针并在包含NULL时抛出异常?或者,还有更好的方法?也许是某种不可空的共享指针?
在您描述的目的中使用共享指针是合理的,并且在C++ 11库中越来越常见.
需要注意的几点:
在API上,将a shared_ptr
作为参数强制调用者构造a shared_ptr
.这绝对是一个很好的举动,其中有一个指针的所有权转移.在函数仅使用a的情况下,shared_ptr
可以接受对象或对象的引用shared_ptr
您正在使用shared_ptr<Parent>
对父对象的后向引用,而在另一个方向上使用一个.这将创建一个保留周期,从而导致永远不会被删除的对象.通常,使用shared_ptr
从上到下weak_ptr
引用时和引用时引用.特别注意委托/回调/观察者对象 - 这些对象几乎总是想要一个weak_ptr
被调用者.如果lambdas异步执行,你还需要注意它们.一种常见的模式是捕获a weak_ptr
.
通过引用而不是值传递共享指针是带有参数支持和反对的风格点.显然,当通过引用传递时,您没有通过所有权(例如,增加对象的引用计数).另一方面,你也没有花费开销.以这种方式引用对象存在危险.在更实际的层面上,使用C++ 11编译器和标准库,传递值应该导致移动而不是复制构造,并且无论如何几乎都是免费的.但是,通过引用传递使得调试变得相当容易,因为您不会重复进入shared_ptr
构造函数.
构造你shared_ptr
的std::make_shared
而不是new()
和shared_ptr
构造函数
shared_ptr<Parent> parent = std::make_shared<Parent>();
使用现代编译器和库,可以节省呼叫new()
.
双方shared_ptr
并weak_ptr
可以包含NULL
-就像任何其他指针可以.你应该总是养成在解除引用之前检查的习惯,也可能是assert()
自由地进行检查.对于构造函数的情况,您始终可以接受NULL
指针,而是抛弃使用点.
您可以考虑使用a typedef
作为共享指针类型.有时使用的一种风格如下:
typedef std::weak_ptr<Parent> Parent_P;
typedef std::shared_ptr<Parent> Parent_WkP;
typedef std::weak_ptr<Child> Child_P;
typedef std::shared_ptr<Child> Child_WkP;
知道在头文件中你可以在shared_ptr<Type>
没有看到完整声明的情况下转发声明也很有用Type
.这可以节省很多头臃肿
归档时间: |
|
查看次数: |
2116 次 |
最近记录: |