'='运算符的默认运算是什么?

时间:2010-09-22 10:39:46

标签: c++

我有一个类Number,它代表一个双点,后面有两位数。在我重载=运算符之前,我运行了一些测试并且有点困惑:

int main(int argc, char **argv) {
    Number *w = new Number(1.111);
    Number *q = new Number(3.444);
    *w = *q;
    std::cout << w->GetNumber() <<std::endl;
    delete q;
    std::cout << w->GetNumber() <<std::endl;

    Number e(5.555);
    Number t = e;
    std::cout <<t.GetNumber() <<std::endl;
}

输出

3.44
3.44
5.55

当'='没有超载时,'='对用户定义对象的默认操作是什么?

我的印象是写作时:

*w = *q;

w指向q(与Java一样)。但是,在我的示例中,我删除了q,而w仍然具有正确的值。

无论如何,当我使用重载= 重载=时,我的作业得分相同。

4 个答案:

答案 0 :(得分:3)

赋值运算符的默认操作是成员赋值:

class Foo
{
    int i;
    std::string s;
    Bar b;

public:

    Foo& operator=(const Foo& that)
    {
        i = that.i;
        s = that.s;
        b = that.b;
        return *this;
    }
};

如果这正是您所需要的,您不必手动重载operator=

如果你有指针成员,只复制指针,而不是复制,这可能会造成严重破坏。在这种情况下使用RAII类型(如std::vector)或通过声明复制构造函数和赋值运算符private或通过继承boost::noncopyable来禁用复制。

请注意Number t = e; 调用赋值运算符,因为还没有要分配的对象。而是调用复制构造函数,它默认执行成员复制构造:

    Foo(const Foo& that) : i(that.i), s(that.s), b(that.b)
    {
    }

因为您可能会问:冒号之后的东西被称为初始化列表。初衷和赋值是C ++中两个截然不同的概念,这一点不容小觑。

答案 1 :(得分:2)

它生成对象的副本(深层副本),即q对象的内容被复制到w。如果您没有提供自己的复制构造函数 - 赋值运算符对,那么编译器将自动为您生成一个,它将源对象的每个元素复制到目标对象的元素。创建此副本后,使用原始对象执行的操作无关紧要。

答案 2 :(得分:2)

* p = * q相当于

(*p).operator=(*q);

默认赋值运算符执行以下操作:(我尝试将其简称但我无法在准确性和简洁性方面超越标准,因此引用它)

X类的隐式定义的复制赋值运算符执行其子对象的成员分配。首先按照它们在base-specifierlist中的声明顺序分配X的直接基类,然后按照它们在类定义中声明的顺序分配X的直接非静态数据成员。每个子对象都以适合其类型的方式分配:

- 如果子对象是类类型,则使用该类的复制赋值运算符(就好像通过显式限定;即忽略更多派生类中的任何可能的虚拟覆盖函数);

- 如果子对象是一个数组,则以适合于元素类型的方式分配每个元素;

- 如果子对象是标量类型,则使用内置赋值运算符。

如您所见,左侧对象没有开始引用右侧对象。

答案 3 :(得分:1)

默认operator =执行对象的成员副本到目的地。

*w = *q*q的值分配给*w;

w = q使w指向与q相同的对象,但它泄漏了w。