在这里,我有一个非常简单的程序,可以将值从一个对象移动到另一个对象,确保从获取它的对象中删除该值(留下“0”)。
#include <iostream>
struct S
{
S(char val) : m_val(val) {}
S& operator=(S&& other) noexcept
{
this->m_val = other.m_val;
other.m_val = '0';
return *this;
}
char m_val = '0';
};
int main()
{
S a('a');
S b('b');
std::cout << "a.m_val = '" << a.m_val << "'" << std::endl;
std::cout << "b.m_val = '" << b.m_val << "'" << std::endl;
a = std::move(b);
std::cout << "a.m_val = '" << a.m_val << "'" << std::endl;
std::cout << "b.m_val = '" << b.m_val << "'" << std::endl;
return 0;
}
正如预期的那样,这个程序的输出是:
a.m_val = 'a'
b.m_val = 'b'
a.m_val = 'b'
b.m_val = '0'
'b' 的值从对象 b 转移到对象 a,留下一个 '0'。现在,如果我用一个模板来概括这一点,以(希望)自动执行移动和删除业务,这就是我最终得到的......(当然是精简的)。
#include <iostream>
template<typename T>
struct P
{
P<T>& operator=(P<T>&& other) noexcept
{
T& thisDerived = static_cast<T&>(*this);
T& otherDerived = static_cast<T&>(other);
thisDerived = otherDerived;
otherDerived.m_val = '0';
return *this;
}
protected:
P<T>& operator=(const P<T>& other) = default;
};
struct S : public P<S>
{
S(char val) : m_val(val) {}
char m_val = '0';
};
int main()
{
S a('a');
S b('b');
std::cout << "a.m_val = '" << a.m_val << "'" << std::endl;
std::cout << "b.m_val = '" << b.m_val << "'" << std::endl;
a = std::move(b);
std::cout << "a.m_val = '" << a.m_val << "'" << std::endl;
std::cout << "b.m_val = '" << b.m_val << "'" << std::endl;
return 0;
}
运行时,输出为:
a.m_val = 'a'
b.m_val = 'b'
a.m_val = '0'
b.m_val = '0'
哦哦!不知何故,两个对象都被“删除”了。当我逐步浏览移动赋值运算符代码的主体时......一切似乎都很好!a.m_val 是'b',就像我们期望的那样......直到return *this;
声明。一旦它从函数返回,该值突然被设置回“0”。任何人都可以阐明为什么会这样吗?