[英]Why doesn't this assignment operator return a copied object?
I have a class called Stack.我有一个名为 Stack 的 class。 I've implemented the copy constructor but for the copy assignment constructor I just have it call the copy constructor since the logic is the same.我已经实现了复制构造函数,但是对于复制赋值构造函数,我只是让它调用复制构造函数,因为逻辑是相同的。 But for some reason it just returns a default constructed object.但由于某种原因,它只返回一个默认构造的 object。 I don't understand why.我不明白为什么。
The copy constructor:复制构造函数:
Stack::Stack( const Stack& s )
{
if ( s.Empty() )
{
this->entry = nullptr;
}
else
{
this->entry = new Entry();
Entry* i = this->entry;
for ( Entry* p = s.entry; p != nullptr; p = p->next )
{
i->number = p->number;
i->next = p->next == nullptr ? nullptr : new Entry();
i = i->next;
}
}
}
The copy assignment constructor:复制赋值构造函数:
Stack& Stack::operator=( const Stack& s )
{
return Stack( s );
}
The calling code:调用代码:
Stack s;
s.Push( 5 );
s.Push( 3 );
Stack s2;
s2 = s; //s2 just ends up defaulted constructed instead of copied from s
If I replace the lines:如果我替换这些行:
Stack s2;
s2 = s;
with:和:
Stack s2(s);
everything works just fine.一切正常。 What am I doing wrong here?我在这里做错了什么?
EDIT --编辑 -
So the lesson here is to implement the assignment ctor and leverage that in the copy ctor, not the other way around as I had done.所以这里的教训是实现分配 ctor 并在复制 ctor 中利用它,而不是像我所做的那样反过来。
The behaviour of your assignment operator is undefined.赋值运算符的行为未定义。
You are returning a dangling reference .您正在返回一个悬空引用。
The idiomatic way of writing the assignment operator is std::move
the instance of the object passed ( s
in your case, which you should pass by value) to self, and return *this
as a reference.编写赋值运算符的惯用方式是std::move
传递s
object 的实例(在你的情况下,你应该按值传递)给 self,并返回*this
作为参考。
Your assignment operator is incorrect.您的赋值运算符不正确。 It is returning a reference to a temporary object.它返回对临时 object 的引用。 It should return *this
instead:它应该返回*this
代替:
Stack& Stack::operator=( const Stack& s )
{
// copy s to members
return *this;
}
If you want to avoid implementing things twice its usually easier to implement the assignment operator and use that in the copy constructor:如果您想避免两次实现事物,通常更容易实现赋值运算符并在复制构造函数中使用它:
Stack::Stack( const Stack& s )
:Stack()
{
*this = s;
}
Stack& Stack::operator=( const Stack& s )
{
if (&s == this) return *this;
// TODO: free current members?
if ( s.Empty() )
{
this->entry = nullptr;
}
else
{
this->entry = new Entry();
Entry* i = this->entry;
for ( Entry* p = s.entry; p != nullptr; p = p->next )
{
i->number = p->number;
i->next = p->next == nullptr ? nullptr : new Entry();
i = i->next;
}
}
return *this;
}
When you do当你这样做
Stack& Stack::operator=( const Stack& s )
{
return Stack( s );
}
Stack(s)
creates an object with a scope limited to the current function. Stack(s)
创建 object,其中 scope 限制为当前 function。 You then return a reference to this local object.然后返回对这个本地 object 的引用。
So, when doing x = y
, x
is not modified to become a copy of y
and a reference to an object that is out of scope is returned, then discarded.因此,在执行x = y
时,不会将x
修改为y
的副本,并且返回对 scope 之外的 object 的引用,然后将其丢弃。
The job of the Stack& Stack::operator=( const Stack& s )
is not to return a copy. Stack& Stack::operator=( const Stack& s )
的工作不是返回副本。 Its job is to modify x
(called this
) so that it becomes equal to y
(called s
).它的工作是修改x
(称为this
)使其等于y
(称为s
)。
So, the proper way would look something like:所以,正确的方法看起来像:
Stack& Stack::operator=( const Stack& s )
{
this->entry = new Entry();
// then all the code to make `this` equal to `s`
}
Since you have a working copy constructor and working destructor for Stack
, you can simply use copy / swap to implement the assignment operator:由于您有Stack
的工作副本构造函数和工作析构函数,因此您可以简单地使用复制/交换来实现赋值运算符:
Stack& Stack::operator=( const Stack& s )
{
if ( this != &s)
{
Stack temp(s);
std::swap(temp.entry, entry);
}
return *this;
}
If you have other member variables, you will need to swap those also.如果你有其他成员变量,你也需要交换它们。
This works by creating a temporary, and simply swapping out the members of the current object ( this
) with the copy's members.这是通过创建一个临时的,并简单地将当前 object ( this
) 的成员替换为副本的成员来实现的。 Then the copy dies off with the old data.然后副本与旧数据一起消失。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.