繁体   English   中英

C ++ API中的智能指针?

[英]Smart pointers in C++ APIs?

经常建议不要在现代C ++中使用原始指针,除非有少数情况。 在C ++库API中使用智能指针的常见做法是什么?

我想到以下用例:

  1. 返回新对象的函数。
  2. 该函数返回一个新对象,但它也创建了对该对象的另一个引用。
  3. 仅使用其接收的对象作为参数的函数。
  4. 接管对象所有权的功能。
  5. 该函数将存储对已作为参数接收到的对象的引用,但是可能存在对同一对象的其他引用(从调用者那一侧)。

不幸的是,库API的设计远远超出了语言本身的规则:突然,您必须关心诸如ABI之类的实现细节。

与普通实现可以轻松交互的C相反,C ++实现具有完全不同的ABI(用于VC ++的Microsoft ABI与gcc和Clang使用的Itanium ABI完全不兼容),并且C ++标准库实现也彼此不兼容,因此如果使用std::类出现在接口中,则使用libstdc ++(与gcc捆绑在一起)编译的库不能被使用libstdc ++的另一个主要版本或libc ++(与Clang捆绑在一起)之类的其他实现的程序使用。

因此,这实际上取决于您是否打算将库作为二进制文件交付,还是取决于用户是否可以使用自己的编译器和标准库实现选择来编译库。 仅在后一种情况下,才应公开C ++接口,因为坚持使用C的二进制发行版更好(并且更易于与其他语言集成)。


顺便说一句,让我们假设您决定使用C ++ API:

1)一个返回新对象的函数。

如果可以按值返回对象,则返回;否则,返回0。 如果它是多态的,请使用std::unique_ptr<Object>

2)一个返回新对象的函数,但它也创建了对该对象的另一个引用。

罕见的情况 我想您的意思是某种程度上已经保留了参考。 在这种情况下,您拥有共享所有权,因此显而易见的选择是std::shared_ptr<Object>

3)仅使用接收到的对象作为参数的函数。

甚至假设不保留对对象的引用,也比最初看起来要复杂得多。

  • 通常,通过引用传递(是否为const
  • 除非您打算对对象的副本进行操作,否则将通过值传递以受益于潜在的移动

4)接管对象所有权的功能。

简单所有权: std::unique_ptr<Object>

5)一个函数,它将存储对已作为参数接收到的对象的引用,但是可能存在对同一对象的其他引用(从调用方)。

共享所有权: std::shared_ptr<Object>

  1. 在一般情况下,唯一指针可以胜任。

     std::unique_ptr<Foo> func(); 

    这样您就可以将它们直接分配给调用者站点上的auto变量,而不必担心内存管理。

     auto u = func(); 

    如果需要共享所有权,可以在调用者站点上转换智能指针:

     std::shared_ptr<Foo> s{func()}; 

    但是,如果函数的返回类型不是多态的, 并且该类型可以快速移动,则您可能更喜欢按值返回

     Foo func(); 
  2. 共享的指针。

     std::shared_ptr<Foo> func(); 
  3. 只需使用对对象的引用或const引用,即可在调用者站点使用原始指针或智能指针“取消引用”。

     void func(Foo& obj); void func(const Foo& obj); 

    如果参数是可选的,则可以使用原始指针,以便可以轻松地将nullptr传递给它们。

     void func(Foo *obj); void func(const Foo *obj); 
  4. 唯一指针。

     void func(std::unique_ptr<Foo> obj); 
  5. 常量引用共享指针。

     void func(const std::shared_ptr<Foo>& obj); 

    const引用(共享指针)只是一种优化,可以防止在调用函数和返回函数时调整引用计数。

这是一个非常古老的问题,但也是一个重要的问题。

答案中缺少一个思路,那就是如果可以帮助您,则不应从API返回原始指针智能指针。

讨论了原始指针问题。 但是,智能指针也可能会被滥用,尤其是在具有复杂内部API的大型项目中。

一种解决方法是创建一个RAII / wrapper对象,该对象保存(从未公开的)智能指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM