C++ 为什么在执行赋值时调用move构造函数?
我正在尝试实现std::unique\u ptr的一个示例。代码如下:C++ 为什么在执行赋值时调用move构造函数?,c++,C++,我正在尝试实现std::unique\u ptr的一个示例。代码如下: include <iostream> template<typename T> class UniquePtr { public: explicit UniquePtr(T * ptr) :m_ptr(ptr) {}; UniquePtr(UniquePtr const & other) = delete; UniquePtr& operator=(Uniq
include <iostream>
template<typename T>
class UniquePtr
{
public:
explicit UniquePtr(T * ptr)
:m_ptr(ptr)
{};
UniquePtr(UniquePtr const & other) = delete;
UniquePtr& operator=(UniquePtr const & other) = delete;
explicit UniquePtr(UniquePtr && other)
{
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
}
UniquePtr & operator=(UniquePtr && other)
{
std::cout << "Move assignment called " << std::endl;
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
}
~UniquePtr()
{
delete m_ptr;
}
T& operator*()
{
return *m_ptr;
}
T& operator->()
{
return m_ptr;
}
private:
T * m_ptr = nullptr;
};
int main()
{
UniquePtr<int> t(new int(3));
t= UniquePtr<int>(new int(4));
std::cout << *t << std::endl;
}
包括
模板
类唯一性
{
公众:
显式唯一性(T*ptr)
:m_ptr(ptr)
{};
UniquePtr(UniquePtr const&other)=删除;
UniquePtr&运算符=(UniquePtr const&其他)=删除;
显式UniquePtr(UniquePtr&其他)
{
m_ptr=其他m_ptr;
other.m_ptr=nullptr;
}
UniquePtr&运算符=(UniquePtr&其他)
{
std::cout在赋值中,调用move是因为UniquePtr(new int(4))
正在构造一个临时对象,在这种情况下,如果可能的话,编译器会尝试使用move赋值,否则它将返回到复制赋值,该赋值将被删除
UniquePtr<int> t(new int(3));
t= UniquePtr<int>(new int(4)); // move assignment because temporary
auto k = t; // copy assignment since t is not temporary and so does not compile.
如果由于任何原因,computeAmount()
函数抛出异常,那么由new
分配的内存将永远无法释放,因为computeAmount()
可以在new
和UniquePtr
的构造函数之间执行。因此,我们通常使用std::make_unique()
您应该实现自己版本的make_unique()
并使用它,它很繁琐,请参见此处:
以下是有关问题和解决方案的更多信息:
t=UniquePtr(新整数(4))
在本例中是一个移动
。相关:你做错的不是从移动赋值操作符返回*这个。这是你唯一做错的事情。你能解释一下为什么你相信移动构造函数会被调用吗?@ChrisMM,我也是这么想的。但为什么会这样呢?你也会这样做吗第一个唯一的ptr?@SamVarshavchik指向的指针,因为该行被打印。我添加了return*this
,但我仍然得到相同的结果。您应该澄清auto k=t;
不会编译。它是一个临时对象,但对象仍然会泄漏,对吗?是否有任何方法可以避免?也许不是无论如何,这是一个真实的用例。如果出于任何原因,香蕉的构造函数抛出异常,那么new分配的内存将永远不会被释放。泄漏场景有点微妙,q.v.是的,在编写示例后,我意识到它不正确,很快就修复了。
class Banana
{ ... }
void eatBanana(UniquePtr<Banana> banana, int amountToEat);
int computeAmount();
eatBanana(UniquePtr<Banana>(new Banana(3)), computeAmount());