繁体   English   中英

为什么这个赋值运算符不返回复制的 object?

[英]Why doesn't this assignment operator return a copied object?

我有一个名为 Stack 的 class。 我已经实现了复制构造函数,但是对于复制赋值构造函数,我只是让它调用复制构造函数,因为逻辑是相同的。 但由于某种原因,它只返回一个默认构造的 object。 我不明白为什么。

复制构造函数:

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;
        }
    }
}

复制赋值构造函数:

Stack& Stack::operator=( const Stack& s )
{
    return Stack( s );
}

调用代码:

Stack s;
s.Push( 5 );
s.Push( 3 );

Stack s2;
s2 = s; //s2 just ends up defaulted constructed instead of copied from s

如果我替换这些行:

Stack s2;
s2 = s;

和:

Stack s2(s);

一切正常。 我在这里做错了什么?

编辑 -

所以这里的教训是实现分配 ctor 并在复制 ctor 中利用它,而不是像我所做的那样反过来。

赋值运算符的行为未定义。

您正在返回一个悬空引用

编写赋值运算符的惯用方式是std::move传递s object 的实例(在你的情况下,你应该按值传递)给 self,并返回*this作为参考。

您的赋值运算符不正确。 它返回对临时 object 的引用。 它应该返回*this代替:

Stack& Stack::operator=( const Stack& s )
{
   // copy s to members
   return *this;
}

如果您想避免两次实现事物,通常更容易实现赋值运算符并在复制构造函数中使用它:

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;
}

当你这样做

Stack& Stack::operator=( const Stack& s )
{
    return Stack( s );
}

Stack(s)创建 object,其中 scope 限制为当前 function。 然后返回对这个本地 object 的引用。

因此,在执行x = y时,不会将x修改为y的副本,并且返回对 scope 之外的 object 的引用,然后将其丢弃。

Stack& Stack::operator=( const Stack& s )的工作不是返回副本。 它的工作是修改x (称为this )使其等于y (称为s )。

所以,正确的方法看起来像:

Stack& Stack::operator=( const Stack& s )
{
    this->entry = new Entry();
    // then all the code to make `this` equal to `s`
}

由于您有Stack的工作副本构造函数和工作析构函数,因此您可以简单地使用复制/交换来实现赋值运算符:

Stack& Stack::operator=( const Stack& s )
{
    if ( this != &s)
    {
       Stack temp(s);
       std::swap(temp.entry, entry);
    }
    return *this;
}

如果你有其他成员变量,你也需要交换它们。

这是通过创建一个临时的,并简单地将当前 object ( this ) 的成员替换为副本的成员来实现的。 然后副本与旧数据一起消失。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM