为方便查阅,此文是原网站文档翻译,如有侵权,请与本人联系。
共享指针
在Chrono中,大多数“重量级对象”,如刚体、链接等,都是通过共享指针进行管理的。一个结果是,用户不必担心在创建对象后删除对象。实际上,这些共享指针在某种意义上提供了一个基本的垃圾收集机制。在这种情况下,Chrono使用STL库中符合C++11的共享指针std::shared_ptr。
shared_ptr类型的对象能够共享指针的所有权。一旦他们获得指针的共享所有权,当最后一个所有者释放该所有权时,该所有者组将负责删除指针。在这种情况下,记住shared_ptr对象在其自身被销毁后立即释放其共同拥有的对象的所有权是很有用的。
在指针上共享所有权的所有shared_ptr对象释放此所有权后,托管对象将自动删除。
使用shared_ptr对象的主要效果是用户永远不需要使用delete。这简化了内存管理,避免了与悬空指针相关的错误。
示例:创建一个对象并通过共享指针处理它。
std::shared_ptr<ChBody> my_body(new ChBody);
但是,同一块内存被两个只能指针管理时会产生错误,因为同一个对象只能用一套内存管理体系,比如
int main(int argc, const char * argv[]) {
auto p1 = new Test; // 划分堆空间
std::shared_ptr<Test> sp(p1); // 创建智能指针
std::shared_ptr<Test> sp2(p1); // 创建另一个智能指针
return 0;
}
一个更好的选择是使用std::make_shared(它需要一个内存分配,速度更快)。但是,std::make_shared将为包含固定大小可向量化特征类型的类的对象使用不正确的分配器。Chrono提供了一个替代函数,它可以自动推断使用std::make_shared回退是否安全。因此,用户代码应始终使用
auto my_body = chrono_types::make_shared<ChBody>();
注意,auto和其他C++11的情况一样,意味着不需要指定
``std::shared_ptr my_body = …
在下一个示例中,构造函数调用中需要参数:
auto my_foo = chrono_types::make_shared<Foo>(par1, par2);
其他指针也可以分配给同一共享对象。示例:
auto my_foo = chrono_types::make_shared<Foo>(par1, par2);
std::shared_ptr<Foo> my_fuu = my_foo;
auto my_fii = FunctionReturningSharedPointer();
向下转换共享指针依赖于dynamic_pointer_cast的使用<…>(…)
通过static_pointer_cast<…>(...)
:完成静态强制转换
从Chrono API的3.0之前版本移植
Chrono API的3.0之前版本使用了自定义共享指针类ChSharedPtr。
这已过时且并被std::shared_ptr
替换.如果遵循以下准则,修改旧代码以使用Chrono API的v.3.0和更高版本将非常简单:
- Types:
- 旧版本
ChSharedPtr<Foo>
- 新版本
std::shared_ptr<Foo>
- 旧版本
- 创建共享指针:
- 旧版本
ChSharedPtr<Foo> my_var(new Foo(arg1, arg2));
- 新版本
auto my_var = chrono_types::make_shared<Foo>(arg1, arg2);
- 旧版本
- 如果Foo的构造函数不接受任何参数,那么:
- 旧版本
ChSharedPtr<Foo> my_var(new Foo);
- 新版本
auto my_var = chrono_types::make_shared<Foo>();
- 旧版本
- 如果变量已经在其他地方声明为共享指针:
- 旧版本
ChSharedPtr<Foo> my_var; my_var = ChSharedPtr<Foo>(new Foo(arg1, arg2));
- 新版本
std::shared_ptr<Foo> my_var; my_var = chrono_types::make_shared<Foo>(arg1, arg2);
- 旧版本
- 复制构造函数:
- 旧版本
ChSharedPtr<Foo> var1; ChSharedPtr<Foo> var2(var1); ChSharedPtr<Foo> var3 = ChSharedPtr<Foo>(var1);
- 新版本
std::shared_ptr<Foo> var1; std::shared_ptr<Foo> var2(var1); auto var3 = std::shared_ptr<Foo>(var1);
- 旧版本
- 来自原始指针的构造函数:
- 旧版本
Foo* my_pointer; ChSharedPtr<Foo> my_var(my_pointer);
- 新版本
Foo* my_pointer; std::shared_ptr<Foo> my_var(my_pointer);
- 旧版本
- 指针转化:
- 旧版本
ChSharedPtr<Base> var1; ChSharedPtr<Derived> var2 = var1.DynamicCastTo<Derived>(); ChSharedPtr<Derived> var3 = var1.StaticCastTo<Derived>();
- 新版本
std::shared_ptr<Base> var1; auto var2 = std::dynamic_pointer_cast<Derived>(var1); auto var3 = std::static_pointer_cast <Derived>(var1);
- 旧版本
- 对包装指针的访问:
- 旧版本
ChSharedPtr<Foo> my_var; Foo* my_pointer = my_var.get_ptr();
- 新版本
std::shared_ptr<Foo> my_var; Foo* my_pointer = my_var.get();
- 旧版本
- 测试NULL(空)共享指针,例如在断言或条件:
- 旧版本
ChSharedPtr<Foo> my_var; assert(!my_var.IsNull());
- 新版本
std::shared_ptr<Foo> my_var; assert(!my_var);
- 旧版本
- 应使用dynamic_pointer_cast显式完成类型测试:
-
旧版本
ChSharedPtr<Bar> my_var; if (my_var.IsType<Foo>()) { .... }
-
新版本
std::shared_ptr<Bar> my_var; if (std::dynamic_pointer_cast<Foo>(my_var)) { ... }
-