更新时间:2023-11-10 08:27:34
你的班级A
有几个问题:
您的赋值运算符不处理自赋值和泄漏:
Your assignment operator don't handle self assignment and leak:
A& A::operator=(const A& a)
{
std::cout<<"overload operator=\n";
if (this != &a)
{
p = a.p;
delete[] s;
s = new char[strlen(a.s) + 1];
strcpy(s, a.s);
}
return *this;
}
你的动作不是移动而是复制:
Your move doesn't move but copy:
A::A(A&& a) : p(a.p), s(a.s)
{
a.s = nullptr;
std::cout << "Move constructor\n";
}
A& A::operator=(A&& a)
{
std::cout << "Move overload operator=\n";
if (this != &a) {
p = a.p;
delete [] s;
s = a.s;
a.s = nullptr;
}
return *this;
}
现在,关于
A make_A()
{
A a(2,"bonapart"); // Constructor
return a;
}
由于潜在的复制省略(NRVO),有几种情况(gcc 有标记为 -fno-elide-constructors
来控制)
There are several scenario because of potential copy elision (NRVO)
(gcc has flag as -fno-elide-constructors
to control that)
如果 NRVO 适用,则 a
是构造就地";所以不会发生额外的破坏/移动;
if NRVO apply, then a
is construct "in-place" so no extra destruction/move happens;
否则有一个移动构造函数和a
的销毁.
else there is a move constructor and the destruction of a
.
A make_A()
{
A a(2,"bonapart"); // #2 ctor(int const char*)
return a; // #3 move (elided with NRVO)
} // #4 destruction of a, (elided with NRVO)
int main()
{
A a1; // #1: default ctor
a1 = // #5: Move assignment (done after make_A)
make_A(); // #6: destructor of temporary create by make_A
a1.display();
} // #8: destructor of a1
使用 NRVO
default ctor
ctor(int const char*)
move assignment
destructor
display
destructor
没有 NRVO (-fno-elide-constructors
)
default ctor
ctor(int const char*)
move ctor
destructor
move assignment
destructor
display
destructor
为了
A a1,a2;
a2 = a1 = make_A();
a1 = make_A();
使用移动赋值.a2 = (a1 = make_A())
使用复制赋值作为移动赋值返回(正确)A&
a1 = make_A();
use move assignment.
a2 = (a1 = make_A())
use copy assignment as move assignment returns (correctly) A&
4在 Move 构造函数和 Move 重载 = 操作符中,我使用了 a.s=nullptr;
这个语句总是在 Move 语义中使用 fredoverflow(user) 解释了类似现在源不再拥有它的对象"之类的东西.但我不明白.因为如果我不写这个语句仍然没有问题一切正常.请解释这一点
4 In Move constructor and Move overloaded = operator I used
a.s=nullptr;
This statement is always used in Move semantics fredoverflow(user) explained something like "now the source no longer owns the object it" but I am not getting it. Because if I did not write this statement still no problem everything works fine. please explain this point
你的问题是你复制而不是移动.
Your issue is that you do copy instead of move.
如果你做 s = a.s;
而不是复制
If you do s = a.s;
instead of the copy
s = new char[strlen(a.s) + 1];
strcpy(s, a.s);
那么 this->s
和 as
都指向相同的数据,this
和 a
> 会在它们的析构函数中释放(相同的)内存 ->双重免费错误.
then both this->s
and a.s
would point of same data, and both this
and a
would free the (same) memory in their destructor -> double free error.
a.s = nullptr;
可以解决这个问题.