为什么在 std::move 函数之后对象仍然存在?
Why does an object still exist after std::move function?
我有一个关于 std::move 函数的问题。请参考以下代码:
#include <iostream>
#include <memory>
using namespace std;
class CPointer {
public:
CPointer(double a, double b)
{
m_dX = a;
m_dY = b;
}
~CPointer()
{
m_dX = m_dY = 0;
}
double getX() const
{return m_dX;}
double getY() const
{return m_dY;}
private:
double m_dX;
double m_dY;
};
class CContainer
{
public:
CContainer(CPointer* p)
{
m_p = p;
}
~CContainer()
{
m_p = nullptr;
}
CPointer* getP() const
{return m_p;}
private:
CPointer* m_p;
};
class CBigContainer
{
public:
CBigContainer(CContainer* p)
{
m_p = p;
}
~CBigContainer()
{
m_p = nullptr;
}
CContainer* getP() const
{return m_p;}
private:
CContainer* m_p;
};
int main()
{
CPointer* pPointer = new CPointer(150,360);
cout << "1.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CContainer> spContainer = std::make_shared<CContainer>(pPointer);
cout << "2.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get())); //<--- std::move here
cout << "3.) " << spBigContainer->getP()->getP()->getX() << " , " << spBigContainer->getP()->getP()->getY() << "\n";
cout << "4.) " << spContainer->getP()->getX() << " , " << spContainer->getP()->getY() << "\n";
cout << "5.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
return 0;
}
这是结果:
我的问题是,我正在使用 std::move
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get()));
所以我预计 spContainer 不能在代码行之后使用,因为智能指针中的对象已被删除。
但它仍然可以正常工作。在这种情况下,似乎与不使用 std::move 没有什么不同。
你能详细解释一下吗?
非常感谢。
So I am expecting the spContainer cannot be used after the line of code, because the object inside smart pointer is removed.
您的代码实际上从未请求任何移动操作。智能指针是一个红色的鲱鱼,你可以在这种情况下看到相同的行为:
C容器a(pPointer);
CBigContainer b( std::move(&a) );
最后一行与CBigContainer b( &a );
相同,因为CBigContainer
的构造函数接受一个指针,原始类型(包括指针)的移动操作行为是保持源不变.
您的代码使 CBigContainer
对象指向 CContainer
对象(后者仍由智能指针管理)。这是个坏主意,因为如果你随后释放 CContainer
智能指针,那么 CBigContainer
指向它的指针将会悬空。
您的 CContainer
和 CBigContainer
对象包含指向其他对象的原始指针。将这些对象放入智能指针中并不会改变这一点。
如果你不清楚,这是两个不同的东西:
- 移出一个智能指针。
- 移出智能指针管理的对象。
第一个将使智能指针为空。第二个让智能指针处于活动状态并管理一个处于 post-移动状态的对象。
下面是一个将移出 spContainer 的代码示例:
std::shared_ptr<CContainer> other = std::move(spContainer);
这会调用一个移动操作,因为左边的 shared_ptr
有一个移动构造函数
它接受另一个相同类型的 shared_ptr
作为参数。
我有一个关于 std::move 函数的问题。请参考以下代码:
#include <iostream>
#include <memory>
using namespace std;
class CPointer {
public:
CPointer(double a, double b)
{
m_dX = a;
m_dY = b;
}
~CPointer()
{
m_dX = m_dY = 0;
}
double getX() const
{return m_dX;}
double getY() const
{return m_dY;}
private:
double m_dX;
double m_dY;
};
class CContainer
{
public:
CContainer(CPointer* p)
{
m_p = p;
}
~CContainer()
{
m_p = nullptr;
}
CPointer* getP() const
{return m_p;}
private:
CPointer* m_p;
};
class CBigContainer
{
public:
CBigContainer(CContainer* p)
{
m_p = p;
}
~CBigContainer()
{
m_p = nullptr;
}
CContainer* getP() const
{return m_p;}
private:
CContainer* m_p;
};
int main()
{
CPointer* pPointer = new CPointer(150,360);
cout << "1.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CContainer> spContainer = std::make_shared<CContainer>(pPointer);
cout << "2.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get())); //<--- std::move here
cout << "3.) " << spBigContainer->getP()->getP()->getX() << " , " << spBigContainer->getP()->getP()->getY() << "\n";
cout << "4.) " << spContainer->getP()->getX() << " , " << spContainer->getP()->getY() << "\n";
cout << "5.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
return 0;
}
这是结果:
我的问题是,我正在使用 std::move
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get()));
所以我预计 spContainer 不能在代码行之后使用,因为智能指针中的对象已被删除。 但它仍然可以正常工作。在这种情况下,似乎与不使用 std::move 没有什么不同。
你能详细解释一下吗? 非常感谢。
So I am expecting the spContainer cannot be used after the line of code, because the object inside smart pointer is removed.
您的代码实际上从未请求任何移动操作。智能指针是一个红色的鲱鱼,你可以在这种情况下看到相同的行为:
C容器a(pPointer);
CBigContainer b( std::move(&a) );
最后一行与CBigContainer b( &a );
相同,因为CBigContainer
的构造函数接受一个指针,原始类型(包括指针)的移动操作行为是保持源不变.
您的代码使 CBigContainer
对象指向 CContainer
对象(后者仍由智能指针管理)。这是个坏主意,因为如果你随后释放 CContainer
智能指针,那么 CBigContainer
指向它的指针将会悬空。
您的 CContainer
和 CBigContainer
对象包含指向其他对象的原始指针。将这些对象放入智能指针中并不会改变这一点。
如果你不清楚,这是两个不同的东西:
- 移出一个智能指针。
- 移出智能指针管理的对象。
第一个将使智能指针为空。第二个让智能指针处于活动状态并管理一个处于 post-移动状态的对象。
下面是一个将移出 spContainer 的代码示例:
std::shared_ptr<CContainer> other = std::move(spContainer);
这会调用一个移动操作,因为左边的 shared_ptr
有一个移动构造函数
它接受另一个相同类型的 shared_ptr
作为参数。