如何将智能指针传递到函数中



将对象传递到函数中时,相同的规则是否适用于智能指针,就像应用于包含动态内存的其他对象一样?

例如,当我将std::vector<std::string>传递到函数中时,我总是考虑以下选项:

  1. 我要更改矢量对象的状态,但我不希望这些更改反映在函数完成后,AKA 制作副本。

    void function(std::vector<std::string> vec);
    
  2. 我要更改矢量对象的状态,并且我确实希望在函数完成后反映这些更改,AKA 进行引用。

    void function(std::vector<std::string> & vec);
    
  3. 这个对象非常大,所以我最好传递一个引用,但告诉编译器不要让我更改它。

    void function(std::vector<std::string> const& vec);  
    

现在,这与智能指针的逻辑相同吗?我什么时候应该考虑移动语义?关于我应该如何传递智能指针的一些指导方针是我最想要的。

智能指针具有指针语义,而不是值语义(好吧,不是你的意思)。把shared_ptr<T>想象成一个T*;这样对待它(好吧,除了引用计数和自动删除)。复制智能指针不会复制它指向的对象,就像复制T*不会复制它指向的T一样。

您根本无法复制unique_ptr。该类的全部意义在于它不能被复制;如果可以,那么它就不会是指向对象的唯一(即:单数)指针。您必须通过某种形式的引用或移动它来传递它。

智能指针都是关于它们所指向内容的所有权。谁拥有此内存,谁将负责删除它。unique_ptr代表唯一的所有权:恰好有一段代码拥有此内存。您可以转移所有权(通过move),但这样做会失去内存的所有权。shared_ptr代表共享所有权。

在所有情况下,在参数列表中使用智能指针都表示转移所有权。因此,如果一个函数采用智能指针,那么它将声明该对象的所有权。如果一个函数不应该获得所有权,那么它根本不应该采用智能指针;使用引用 (T&),或者如果您需要可空性,请使用指针,但从不存储它。

如果你通过某人一个unique_ptr,你就给了他们所有权。这意味着,由于唯一所有权的性质,您正在失去对内存的所有权。因此,除了价值之外,几乎没有理由通过任何东西传递unique_ptr

同样,如果要共享某个对象的所有权,则传入shared_ptr.您是通过参考还是按价值来做到这一点取决于您。由于您共享所有权,因此无论如何它都会复制(大概),因此您不妨按价值获取它。该函数可以使用std::move将其移动到类成员等中。

如果函数不打算修改或复制指针,只需使用哑指针即可。智能指针用于控制对象的生存期,但该函数不会更改生存期,因此它不需要智能指针,并且使用哑指针可以在调用方使用的类型方面提供一些灵活性。

void function(std::string * ptr);
function(my_unique_ptr.get());
function(my_shared_ptr.get());
function(my_dumb_ptr);

unique_ptr不能在不使原件失效的情况下复制,因此如果必须传递它,则必须传递引用。

要更深入地了解比我聪明得多的人的这个建议,请参阅 Herb Sutter 的 GotW #91 解决方案:智能指针参数。 他超越了这个建议,并建议如果指针不能为 null,则应通过引用而不是指针传递。 这需要在调用站点取消引用指针。

void function(std::string & val);
assert(my_unique_ptr != nullptr && my_shared_ptr != nullptr && my_dumb_ptr != nullptr);
function(*my_unique_ptr);
function(*my_shared_ptr);
function(*my_dumb_ptr);

智能指针是引用另一个对象并管理其生存期的对象。

传递智能指针需要遵守智能 poitner 支持的语义:

  • const smartptr<T>&传递始终有效(您无法更改指针,但可以更改其指向的状态)。
  • 传递smartptr<T>&始终有效(您也可以更改指针)。
  • 仅当smartptr可复制时,作为smartptr<T>传递(通过副本)才有效。它适用于std::shared_ptr,但不适用于std::unique_ptr,除非你在调用时"移动"它,就像在func(atd::move(myptr))中一样,从而使myptr无效,将指针移动到传递的参数。(请注意,如果移动是临时的,则移动是隐式的myptr)。
  • smartptr<T>&&传递(通过移动)通过强制您显式使用std::move来强制要在调用时移动指针(但需要"移动"才能对特定指针有意义)。
  • 我知道问这个问题的人在C++方面比我知识渊博,这个问题有一些完美的答案,但我相信这个问题最好以一种不会吓到人们的方式回答C++,尽管它可能有点复杂,这是我的尝试:

考虑到C++中只有一种类型的智能指针,它是shared_ptr的,所以我们有以下选项将其传递给函数:

1 - 按void f(std::shared_ptr<Object>);

2 -参考void f(std::shared_ptr<Object>&);

最大的区别是,第一个借给你所有权,第二个让你操纵所有权。

进一步阅读和详细信息可以在这个链接上,这之前对我有帮助。

相关内容

  • 没有找到相关文章

最新更新