C++ 使用std::在std::shared上移动\u ptr<;SomeClass>;正确地

C++ 使用std::在std::shared上移动\u ptr<;SomeClass>;正确地,c++,c++11,c++14,shared-ptr,smart-pointers,C++,C++11,C++14,Shared Ptr,Smart Pointers,我正在做一个项目,处理共享的\u ptr。程序正在运行并给出正确的输出。然而,在查看日志时,我注意到在程序中的某些点上,引用计数具有特定的值。样品再现程序如下所示: 示例程序 #include <iostream> #include<vector> #include<string> #include<utility> #include<memory> class NAME { public: std::strin

我正在做一个项目,处理
共享的\u ptr
。程序正在运行并给出正确的输出。然而,在查看日志时,我注意到在程序中的某些点上,引用计数具有特定的值。样品再现程序如下所示:

示例程序

#include <iostream>
#include<vector>
#include<string>
#include<utility>
#include<memory>
class NAME 
{   
    public:
    std::string name;
    int age = 12;
    
    
    NAME(std::string m_name, int m_age):name(m_name), age(m_age)
    {
        std::cout<<"NAME Parametrised "<<std::endl;
        
    }
    NAME(const NAME& rhs):name(rhs.name), age(rhs.age)
    {
        std::cout<<"NAME Copy constructor"<<std::endl;
    }
};
class SURNAME 
{
    public:
    std::vector<std::vector<std::shared_ptr<NAME>>> vec_2d;
    SURNAME(const std::vector<std::vector<std::shared_ptr<NAME>>> &m_vec):vec_2d(m_vec) 
    {
        std::cout<<"Refernce count in SURNAME para constructor: "<<vec_2d.at(0).at(0).use_count()<<std::endl;
    }
    
};
class AN
{
    public:
      std::vector<SURNAME> vec_SURNAME;
};

int main()
{

   
   std::vector<std::shared_ptr<NAME>> temp_vector;
   temp_vector.reserve(3);
   temp_vector.push_back(std::make_shared<NAME>("MIDDLE",43));
   temp_vector.push_back(std::make_shared<NAME>("LAST",54));
   temp_vector.push_back(std::make_shared<NAME>("ANOTHERLAST",54));
   std::vector<std::vector<std::shared_ptr<NAME>>> temp_2dvec;
   temp_2dvec.reserve(1);
   temp_2dvec.push_back(temp_vector);//reference count becomes 2
   
   AN obj;
   
   obj.vec_SURNAME.push_back(temp_2dvec);//reference count becomes 3

   return 0;
}
正如我们在输出中看到的,构造函数中的引用计数为3。我认为当我们写
temp\u2dvec.push\u back(temp\uvector)引用计数增加1,然后当我们写入
obj.vec\u name.push\u back(temp\u 2dvec)时引用计数再次增加1,最后变为3。现在我的问题是:

  • 有没有办法避免引用计数的增加而移动共享\u ptr?如果是,那怎么办?例如,我尝试使用
    temp_2dvec.push_back(std::move(temp_vector))则在该步骤中引用计数没有增加。在这一步中这样做可以吗,还是某种形式的UB
  • 当我尝试做同样的事情,并使用语句
    obj.vec_-name.push_-back(std::move(temp_-2dvec))那么即使在这里使用std::move()时,引用计数仍然会增加。这是怎么发生的
  • 注意,变量
    temp_vector
    temp_2dvec
    只是我用来保存向量的临时变量。它们仅用于推送目的一次。所以我不会使用它们。所以离开他们是安全的。我如何才能安全地实现这一点,即当推到向量上时,引用计数不应增加
  • 另外,我的2条评论是否正确(那些我写在主程序语句右侧的评论)?也就是说,参考计数在这两个步骤中增加,或者在我缺少的程序的某个其他区域/步骤中增加
  • 我尝试使用temp_2dvec.push_back(std::move(temp_vector));然后在这一步中引用计数没有增加。在这一步中这样做可以吗,还是某种形式的UB

    std::move
    本身不会移动或优化任何东西,它只是一个工具。但是,由于参数类型不同,使用移动对象的代码可以对其进行不同的处理。标准库类可以做到这一点,例如:

    移动赋值运算符。使用移动语义将内容替换为other的内容(即,other中的数据从other移动到此容器中)。之后,另一个处于有效但未指定的状态

    因此,是的,您应该使用
    std::move
    ,至少标准库会更有效地处理它

    当我尝试做同样的事情,并使用语句obj.vec_姓氏.push_back(std::move(temp_2dvec));即使在这里使用std::move(),引用计数仍然会增加。这是怎么发生的

    但您当前的代码没有:

        std::vector<std::vector<std::shared_ptr<NAME>>> vec_2d;
        SURNAME(const std::vector<std::vector<std::shared_ptr<NAME>>> & m_vec):vec_2d(m_vec) 
        {
            std::cout<<"Refernce count in SURNAME para constructor: "<<vec_2d.at(0).at(0).use_count()<<std::endl;
        }
    
    这里的参数类型不同于
    std::vector&
    ,可以安全地将其移动,而不是使用
    vec_2d(std::move(m_vec))
    进行复制

    另一种方法是使用单个方法,而不是对复制和移动使用多个重载:

        SURNAME(std::vector<std::vector<std::shared_ptr<NAME>>> m_vec):vec_2d(std::move(m_vec))
        {
            std::cout<<"Refernce count in SURNAME para constructor: "<<vec_2d.at(0).at(0).use_count()<<std::endl;
        }
    
    姓氏(std::vector m_vec):vec_2d(std::move(m_vec))
    {
    标准::cout
    
        SURNAME(std::vector<std::vector<std::shared_ptr<NAME>>> && m_vec):vec_2d(std::move(m_vec))
        {
            std::cout<<"Refernce count in SURNAME para constructor: "<<vec_2d.at(0).at(0).use_count()<<std::endl;
        }
    
        SURNAME(std::vector<std::vector<std::shared_ptr<NAME>>> m_vec):vec_2d(std::move(m_vec))
        {
            std::cout<<"Refernce count in SURNAME para constructor: "<<vec_2d.at(0).at(0).use_count()<<std::endl;
        }