繁体   English   中英

类分配运算符

[英]Class Assignment Operators

我做了以下运算符重载测试:

#include <iostream>
#include <string>

using namespace std;

class TestClass
{
    string ClassName;

    public:

    TestClass(string Name)
    {
        ClassName = Name;
        cout << ClassName << " constructed." << endl;
    }

    ~TestClass()
    {
        cout << ClassName << " destructed." << endl;
    }

    void operator=(TestClass Other)
    {
        cout << ClassName << " in operator=" << endl;
        cout << "The address of the other class is " << &Other << "." << endl;
    }
};

int main()
{
    TestClass FirstInstance("FirstInstance");
    TestClass SecondInstance("SecondInstance");

    FirstInstance = SecondInstance;
    SecondInstance = FirstInstance;

    return 0;
}

赋值运算符的行为与预期一致,输出另一个实例的地址。

现在,我如何实际分配来自其他实例的内容? 例如,像这样:

void operator=(TestClass Other)
{
    ClassName = Other.ClassName;
}

赋值运算符的传统规范形式如下所示:

TestClass& operator=(const TestClass& Other);

(您也不想调用复制构造函数进行赋值)并返回对*this的引用。

一个简单的实现将分别为每个数据成员分配:

TestClass& operator=(const TestClass& Other)
{
  ClassName = Other.ClassName;
  return *this;
}

(请注意,这正是编译器生成的赋值运算符所要做的,因此重载它是没有用的。不过我认为这是用于练习。)

更好的方法是采用Copy-And-Swap习语 (如果你发现GMan的答案过于庞大,请尝试我的 ,这不是那么详尽。 :) )请注意,C&S使用复制构造函数和析构函数来进行赋值,因此需要按照副本传递对象,就像在问题中一样:

TestClass& operator=(TestClass Other)

你展示的代码就是这样做的。 但是,没有人会认为这是一个特别好的实施。

这符合赋值运算符的预期:

TestClass& operator=(TestClass other)
{
    using std::swap;
    swap(ClassName, other.ClassName);
    // repeat for other member variables;
    return *this;
}

顺便说一下,你谈的是“其他类”,但你只有一个类,以及该类的多个实例。

几乎所有人都说了几句

  • 检查自我分配,即if (&other != this) // assign
  • 在这里查看有关运算符重载的出色指南

传统的赋值运算符和复制构造函数定义为传递const引用,而不是按值复制机制。

class TestClass 
{
public:
    //... 
    TestClass& operator=(const TestClass& Other)
    {
        m_ClassName= Other.m_ClassName;
        return *this;
    }
private:
    std::string m_ClassName;
 }

编辑:我纠正了因为我把代码没有返回TestClass&(cf @sbi的回答)

您对如何从其他类复制内容是正确的。 可以使用operator=分配简单对象。

但是,要小心TestClass包含指针成员的情况 - 如果你只是使用operator=分配指针,那么两个对象都会有指向同一内存的指针,这可能不是你想要的。 您可能需要确保分配一些新内存并将指向的数据复制到其中,以便两个对象都拥有自己的数据副本。 请记住,在为复制的数据分配新块之前,还需要正确释放已分配给对象已指向的内存。

顺便说一下,你应该声明你的operator=这样:

TestClass & operator=(const TestClass & Other)
{
    ClassName = Other.ClassName;
    return *this;
}

这是重载operator=时使用的一般约定。 return语句允许链接分配(如a = b = c )并通过const引用传递参数,避免在进入函数调用的过程中复制Other

暂无
暂无

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

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