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

C++ 如何将智能指针传递到函数中?,c++,c++11,parameter-passing,smart-pointers,unique-ptr,C++,C++11,Parameter Passing,Smart Pointers,Unique Ptr,将对象传递到函数时,智能指针是否与包含动态内存的其他对象适用相同的规则 当我通过一个 STD::vector 函数时,我总是考虑以下选项: 我将更改向量对象的状态,但我不希望在函数完成后反映这些更改,也就是复制 void function(std::vector<std::string> vec); void函数(std::vector-vec); 我将更改向量对象的状态,我希望这些更改在函数完成后反映出来,也就是做一个引用 void function(std::vector&l

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

当我通过一个<代码> STD::vector <代码>函数时,我总是考虑以下选项:

  • 我将更改向量对象的状态,但我不希望在函数完成后反映这些更改,也就是复制

    void function(std::vector<std::string> vec);
    
    void函数(std::vector-vec);
    
  • 我将更改向量对象的状态,我希望这些更改在函数完成后反映出来,也就是做一个引用

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

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

  • 这和智能指针的逻辑是一样的吗?什么时候我应该考虑移动语义学?关于如何传递智能指针的一些指导原则是我最想要的。

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

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

    • 作为
      const smartptr&
      传递始终有效(您不能更改指针,但可以更改指针指向的状态)
    • 作为
      smartptr&
      传递始终有效(您也可以更改指针)
    • 仅当smartptr可复制时,作为smartptr传递(通过复制)才有效。它适用于
      std::shared齌ptr
      ,但不适用于
      std::unique齌ptr
      ,除非您在调用时“移动”它,如在
      func(atd::move(myptr))
      中,从而使
      myptr
      无效,移动指向传递参数的指针。(请注意,如果
      myptr
      是临时的,则移动是隐式的)
    • 通过强制您显式使用
      std::move
      (但需要“move”才能对特定指针有意义),作为
      smartptr&&
      传递(通过移动)强制在调用时移动指针
      • 智能指针有指针语义,而不是值语义(好吧,不是你的意思)。把
        shared_ptr
        想象成
        T*
        ;这样对待它(除了引用计数和自动删除)。复制智能指针不会复制它指向的对象,就像复制
        T*
        不会复制它指向的
        T
        一样

        您根本无法复制
        唯一\u ptr
        。这个类的全部要点是它不能被复制;如果可以,那么它就不是指向对象的唯一(即:单数)指针。您必须通过某种形式的引用或移动来传递它

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

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

        如果您向某人传递一个
        唯一的\u ptr
        ,则表示您给予了他们所有权。这意味着,由于独特所有权的性质,您正在失去对内存的所有权。因此,除了按值传递外,几乎没有任何理由传递
        唯一的\u ptr


        类似地,如果您想共享某个对象的所有权,您可以传入一个
        shared\u ptr
        。你是通过参考还是通过价值来做这件事取决于你自己。由于您共享所有权,它无论如何都会复制(大概是这样),所以您不妨按价值来获取它。该函数可以使用
        std::move
        将其移动到类成员或类似对象中。

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

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

        unique\u ptr
        无法复制,因此如果必须通过,则必须通过引用。

        unique\u ptr
        不可复制,您必须手动复制<代码>标准::唯一的ptr(mew T(*其他ptr))除此之外,它应该与向量相同。请参见和“移动语义的处理方法是什么?”这是一个完全不同的问题,已经被询问和回答。“pssign as smartptr&&(by move)”&&并不意味着移动。在非模板推断参数参数中使用r值引用意味着只能向函数传递一个可以绑定到r值引用的表达式。因此,从函数返回一个临时或
        T&
        。除非你构造一个对象,否则不会发生实际的移动。@NicolBolas:这正是我的概念:“强制移动”,强制使用std::move,否则函数不会绑定。如果我重写的话可能会更好…-1:事实错误:“仅当smartptr可复制时,作为smartptr的密码(通过复制)才有效”这根本不是真的。“传递”值对于仅移动类型非常有效。你必须进入这个论点。@尼可博拉斯:请理解我的答案的语义遵循的问题之一,不是C++规范,而是用相反的方式来阐述概念。正如您所说的“传递值对于仅移动的类型很有效。您只需移动到参数中即可。”但这样做之后,您就没有了副本(