23

将对象传递给函数时,是否适用于智能指针与其他包含动态内存的对象相同的规则?

例如,当我将 a 传递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);  
    

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

4

4 回答 4

34

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

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

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

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

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

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

于 2012-09-20T20:00:30.460 回答
6

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

void function(std::string * ptr);

function(my_unique_ptr.get());
function(my_shared_ptr.get());
function(my_dumb_ptr);

unique_ptr不能复制,所以如果你必须通过它,你必须通过参考。

于 2012-09-20T20:14:34.080 回答
5

智能指针是一个对象,它引用另一个管理其生命周期的对象。

传递智能指针需要尊重智能指针支持的语义:

  • 传递const smartptr<T>&一如既往的工作(你不能改变指针,但可以改变它指向的状态)。
  • smartptr<T>&往常一样通过(您也可以更改指针)。
  • 仅当smartptr可复制时,传递 as smartptr<T>(通过复制)才有效。它适用于,但不适用于,除非您在调用时“移动”它,例如 in ,从而使 无效,将指针移动到传递的参数。(请注意,如果是临时的,则 move 是隐式的)。std::shared_ptrstd::unique_ptrfunc(atd::move(myptr))myptrmyptr
  • 作为smartptr<T>&&(通过移动)传递通过强制您显式使用std::move(但需要“移动”以对特定指针有意义)来强制在调用时移动指针。
于 2012-09-20T19:59:50.423 回答
0
  • 我知道问这个问题的人在 C++ 方面比我知识渊博,并且这个问题有一些完美的答案,但我相信这个问题最好以一种不会吓到 C++ 的人的方式回答,尽管它可能会有点复杂,这是我的尝试:

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

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

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

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

进一步的阅读和细节可以在这个链接上,这对我有帮助。

于 2021-09-18T09:31:08.777 回答