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;
}