Псевдоним переменной не работает при перегрузке оператора - PullRequest
1 голос
/ 02 июня 2019

Я изучаю перегрузку оператора. Я пытаюсь перегрузить + оператор в моем коде. Когда я возвращаюсь с неявной разыменовкой, вывод - бред.

Если я явно отменю ссылку на переменную при возврате, она будет работать правильно. Проблема возникает из-за того, что я ссылаюсь на некоторую временную переменную, и она удаляется после выхода из области видимости. Если так, то почему работает явная разыменование? Постскриптум : Я знаю, что могу вернуться без ссылки, и я не соблюдаю правило 3 в коде.


class ComplexNum
{
private:
    int real, imaginary;
public:
    ComplexNum();
    ComplexNum(int x, int y);
    ComplexNum(const ComplexNum& other);
    ~ComplexNum();

    int getReal() const;
    int getImaginary() const;

    const ComplexNum& operator=(const ComplexNum&);
    friend std::ostream& operator <<(std::ostream& out, const ComplexNum& a);
    ComplexNum& operator+(const ComplexNum&);
};

ComplexNum::ComplexNum()
{
}

ComplexNum::ComplexNum(int x, int y):real(x), imaginary(y)
{
}

ComplexNum::ComplexNum(const ComplexNum& other)
{
    this->real = other.real;
    this->imaginary = other.imaginary;
}

ComplexNum::~ComplexNum()
{
}


int ComplexNum::getReal() const
{
    return real;
}

int ComplexNum::getImaginary() const
{
    return this->imaginary;
}

const ComplexNum& ComplexNum::operator=(const ComplexNum& other)
{
    real = other.real;
    imaginary = other.imaginary;

    return *this;
}

ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
    ComplexNum a(real + other.getReal(), imaginary + other.getImaginary());
    return a;
}

/*the above one doesn't work but the below commented out works fine.*/
/*
ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
    ComplexNum* a = new ComplexNum(real + other.getReal(), imaginary + other.getImaginary());
    return *a;
}*/

std::ostream& operator<<(std::ostream& out,const ComplexNum& a)
{
    out << a.real << " & " << a.imaginary << "j";
    return out;
}


/*Here is how I am calling it in main*/
int main()
{
    ComplexNum complex(3, 4);
    ComplexNum c2(5, 6);
    cout << c2 << endl;
    ComplexNum& c3 = c2 + complex;
/*getting error in the below code. c3 is o/p gibberish value as if not initialized*/
    cout << c3<< " " << c2 << endl;
    return 0;
}

Я получаю бессмысленное значение, как будто переменная c3 не инициализирована.

1 Ответ

0 голосов
/ 02 июня 2019

Этот код вызывает утечку памяти, поскольку указатель a автоматически удаляется после достижения конца области, и у вас нет возможности удалить память, выделенную в куче на new. К несчастью для вас, вы разыменовали a непосредственно перед его удалением в операторе return, и вы смогли получить доступ к его значению, думая, что все в порядке.

ComplexNum& ComplexNum::operator+(const ComplexNum& other)
{
    ComplexNum* a = new ComplexNum(real + other.getReal(), imaginary + other.getImaginary());
    return *a;
}

Если честно, большая часть кода, которую вы имеете, может быть исключена с помощью спецификатора = default или вообще без него. Используйте его, потому что он облегчает чтение кода.

Операторы, которые используются для возврата нового экземпляра класса (например, +,-,*,/), не должны возвращаться по ссылке. Операторы, которые изменяют текущий экземпляр класса (например, =,+=,-=,*=,/=), должны быть возвращены по ссылке.

#include <iostream>

struct ComplexNum
{
    int real;
    int imaginary;

    ComplexNum() = default;
    ComplexNum(int x, int y) : real(x), imaginary(y)
    {;}

    friend std::ostream& operator <<(std::ostream& out, const ComplexNum& a)
    {
        out << a.real << " & " << a.imaginary << "j";
        return out;
    }

    ComplexNum operator + (const ComplexNum &other)
    {
        int r = this->real + other.real;
        int i = this->imaginary + other.imaginary;
        return ComplexNum(r,i);
    }

    ComplexNum& operator += (const ComplexNum &other)
    {
        this->real += other.real;
        this->imaginary += other.imaginary;
        return *this;
    }

    ~ComplexNum() = default;
};


int main()
{
    ComplexNum c1(3, 4);
    std::cout << c1 << std::endl;

    ComplexNum c2(5, 6);
    std::cout << c2 << std::endl;

    ComplexNum c3 = c1 + c2;
    std::cout << c3 << std::endl;

    c3 += c1;
    std::cout << c3 << std::endl;
}

Результаты:

3 & 4j
5 & 6j
8 & 10j
11 & 14j

Пример кода онлайн: https://rextester.com/QNR88316

...