为什么我的重载操作符+使这个'这个'在向自身添加变量时返回时未初始化?

时间:2017-04-13 04:13:13

标签: c++ operator-overloading

我在我的代码中发现了一个错误,其中包含我的驱动程序中的行

t2 = t2 + t;

导致这个'在我重载的操作符+返回期间变得未初始化。使用调试工具我的代码似乎执行完全正常,直到返回调用,然后当我进入内部返回它带我到我的复制构造函数'这'指向与传入其中的p参数相同的头节点。但是,一旦我将复制构造函数标题移入正文中,就会出现这种情况。突然改变它的内存位置并指向0xcccccccc,告诉我它没有初始化,这导致我的构造函数出现问题,因为它不是空值。

我希望有人可以让我深入了解究竟发生了什么,以及如何解决这个问题。显然我可以使用我的运算符+ =因为它工作正常,但理论上你应该能够毫无错误地进行这种调用。

编辑:在收到指出我不知道要做得更好的明显错误的评论之后,我编辑了我的代码,包括帮助副本和清除方法,以便在我的复制构造函数,析构函数和赋值运算符中使用。

更新实施:

#include "polynomial.h" //header
#include <stdlib.h>

// Default Constructor:the default is a 0-degree polynomial with 0.0 coefficient

Polynomial::Polynomial() {
    size = 0;
    head = new Term;
    head->coeff = 0;
    head->power = 0;
    head->next = head;
    head->prev = head;
}

// Copy Constructor

Polynomial::Polynomial(const Polynomial &p) {
    copy(p);
}

// Destructor

Polynomial::~Polynomial() {
    clear();
}

// degree: returns degree of polynomial
// Pre: none (an empty polynomial will return as a 0-degree)
// Post: the largest degree in the polynomial is returned as an int

int Polynomial::degree() const {
    return head->next->power;
}

// coefficient: returns the coefficient of the x^power Term
// Pre: none
// Post: the coefficient, if an x^power Term exists, is return. If 
//      an x^power Term doesn't exist, 0 is returned

double Polynomial::coefficient(const int power) const {
    Term *thisPointer = head->next;
    while (thisPointer->power != power && thisPointer != head) thisPointer = thisPointer->next;
    if (thisPointer == head) return 0;
    return thisPointer->coeff;
}

// changeCoefficient: replaces the coefficient of the x^power term
// Pre: none
// Post: if an x^power Term exists, its coefficient will be changed to 
//      newCoefficient. If not, an x^power Term with that coefficient will be inserted

bool Polynomial::changeCoefficient(const double newCoefficient, const int power) {
    if (head == NULL) *this = Polynomial();
    Term *thisPointer = head->next;
    // either finds value to be changed or stops before head, indicating need for insertion
    while (thisPointer->power != power && thisPointer->next != head)
        thisPointer = thisPointer->next;
    // finds proper location for insertion if cycled through list
    if (thisPointer->next == head) {
        thisPointer = head;
        while (thisPointer->next->power > power) thisPointer = thisPointer->next;
        insert(thisPointer->next, newCoefficient, power);
    }
    else if (newCoefficient == 0) {
        remove(thisPointer);
    } else thisPointer->coeff = newCoefficient;
    return true;
}

// insert: inserts an x^power Term with coefficient newCoefficient into the
//      polynomial, directly just before the pos Term
// Pre: the function is passed a nonzero newCoefficient and a pos Term that
//      exists in the polynomial
// Post: returns true if new Term was successfully inserted, returns false if
//      pre conditions are not met

bool Polynomial::insert(Term* pos, const double newCoefficient, const int power) {
    if (newCoefficient == 0) return false;
    Term *thisPointer = head;
    while (thisPointer->next != pos && thisPointer->next != head)
        thisPointer = thisPointer->next;
    // returns false if pos Term is not found
    if (size > 0 && thisPointer->next == head && pos != head) return false;
    // creates new term using parameters
    Term *newTerm = new Term;
    newTerm->power = power;
    newTerm->coeff = newCoefficient;
    // redirects pointers of adjacent Terms to include newTerm in polynomial
    newTerm->next = thisPointer->next;
    newTerm->prev = thisPointer;
    thisPointer->next->prev = newTerm;
    thisPointer->next = newTerm;
    size++;
    return true;
}

// remove: removes pos Term from polynomial
// Pre: pos Term exists in polynomial
// Post: returns true if pos Term was successfuly removed, if not returns false

bool Polynomial::remove(Term* pos) {
    Term *thisPointer = head;
    // finds term before one to be deleted
    while (thisPointer->next != pos && thisPointer->next != head) thisPointer = thisPointer->next;
    //returns false if pos term is not found
    if (thisPointer->next == head) return false;
    // redirects pointers of adjacent Terms around pos, removes pos
    thisPointer->next = thisPointer->next->next;
    thisPointer->next->prev->prev = NULL;
    thisPointer->next->prev->next = NULL;
    delete thisPointer->next->prev;
    thisPointer->next->prev = thisPointer;
    size--;
    return true;
}

// clear: removes all terms of polynomial from memory
// Pre:
// Post: 
void Polynomial::clear() {
    if (head != NULL) {
        while (head->next != head) {
            Term *thisPointer = head;
            head = head->next;
            remove(thisPointer);
        }
        head->next = head;
        head->prev = head;
        head->coeff = 0;
    }
}

// copy:
// Pre:
// Post: 
void Polynomial::copy(const Polynomial &p) {
    Term *pPointer = p.head;
    if (pPointer == NULL) head = NULL;
    else {
        head = new Term;
        head->coeff = 0;
        head->power = 0;
        head->next = head;
        head->prev = head;
        size = p.size;
        //copy rest of polynomial
        Term *thisPointer = head;
        while (pPointer->next != p.head) {
            pPointer = pPointer->next;
            double coeff = pPointer->coeff;
            int power = pPointer->power;
            // create new Term with data from Term in p
            Term *newTerm = new Term;
            thisPointer->next = newTerm;
            newTerm->prev = thisPointer;
            newTerm->coeff = coeff;
            newTerm->power = power;
            thisPointer = thisPointer->next;
            // checks for end of p to link head and last term
            if (pPointer->next == p.head) {
                head->prev = thisPointer;
                thisPointer->next = head;
            }
        }
    }
}

// Overloaded <<: prints Cn * x^n + Cn-1 * X^n-1 + ... C1 * X + C0

ostream& operator<<(ostream &output, const Polynomial& p) {
    Polynomial::Term *thisPointer = p.head->next;
    if (thisPointer != NULL) {
        while (thisPointer != p.head) {
            if (thisPointer->coeff < 0) output << "-";
            else if (thisPointer->prev != p.head) output << " + ";
            if (abs(thisPointer->coeff) != 1) output << abs(thisPointer->coeff);
            if (abs(thisPointer->power) == 1) output << "x";
            else if(thisPointer->power != 0) output << "x^" << thisPointer->power;
            thisPointer = thisPointer->next;
        }
    }
    return output;
}

// Overloaded operator+

Polynomial Polynomial::operator+(const Polynomial &in) const {
    Polynomial out = *this;
    out += in;
    return out;
}

// Overloaded operator-

Polynomial Polynomial::operator-(const Polynomial &in) const {
    Polynomial out = *this;
    out -= in;
    return out;
}

// Overloaded operator==

bool Polynomial::operator==(const Polynomial &in) const {
    Term *thisPointer = head->next;
    Term *inPointer = in.head->next;
    while (thisPointer != head || inPointer != in.head) {
        if (thisPointer->power != inPointer->power || 
            thisPointer->coeff != inPointer->coeff) return false;
        thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return true;
}

// Overloaded operator!=

bool Polynomial::operator!=(const Polynomial &in) const {
    return !(*this == in);
}

// Overloaded operator=

Polynomial& Polynomial::operator=(const Polynomial &p) {
    if (*this != p) {
        clear();
        copy(p);
    }
    return *this;
}

// Overloaded operator+=

Polynomial& Polynomial::operator+=(const Polynomial &in) {
    Term *thisPointer = head;
    Term *inPointer = in.head;
    while (thisPointer->next != head || inPointer->next != in.head) {
        int power = inPointer->next->power;
        double coeff = inPointer->next->coeff;
        // if t > p, insert t in p
        if (power > thisPointer->next->power) {
            insert(thisPointer->next, coeff, power);
            thisPointer = thisPointer->next;
        }
        // if p power = t power, add 
        else if (power == thisPointer->next->power)
            thisPointer->next->coeff += coeff;
        if (thisPointer->next->coeff == 0) remove(thisPointer->next);
        // only advances t if p->next isn't larger than t->next
        if (inPointer->next->power <= thisPointer->next->power)
            thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return *this;
}

// Overloaded operator-=

Polynomial& Polynomial::operator-=(const Polynomial &in) {
    Term *thisPointer = head;
    Term *inPointer = in.head;
    while (thisPointer->next != head || inPointer->next != in.head) {
        int power = inPointer->next->power;
        double coeff = inPointer->next->coeff;
        // if t > p, insert t in p
        if (power > thisPointer->next->power) {
            insert(thisPointer->next, -coeff, power);
            thisPointer = thisPointer->next;
        }
        // if p power = t power, subtract 
        else if (power == thisPointer->next->power)
            thisPointer->next->coeff -= coeff;
        if (thisPointer->next->coeff == 0) remove(thisPointer->next);
        // only advances t if p->next isn't larger than t->next
        if (inPointer->next->power <= thisPointer->next->power)
            thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return *this;
}

驱动程序文件:

#include <iostream>
using namespace std;

#include "polynomial.h"

int main() {
    Polynomial t;

    // adds new Terms using changeCoefficient
    t.changeCoefficient(1, 1);
    t.changeCoefficient(2, 2);
    t.changeCoefficient(3, 3);
    t.changeCoefficient(4, 5);
    t.changeCoefficient(-5, 4);

    cout << "t = " << t << endl;
    // degree() demonstration
    cout << "t's degree = " << t.degree() << endl;

    // changing coefficients/deleting terms/adding constant value
    t.changeCoefficient(1, 3);
    t.changeCoefficient(9, 0);
    t.changeCoefficient(0, 5);

    cout << "t = " << t << endl;
    cout << "t's degree = " << t.degree() << endl;

    // copy constructor and operator= demonstration
    Polynomial t2 = t + t;
    // operator+ demonstration
    t2 = t2 + t;

    cout << "t2 = " << t2 << endl;

    // operator!= demonstration
    cout << "t2 does not equal t, right? " << boolalpha << (t2 != t) << endl;

    // operator- demonstration
    Polynomial t3 = t - t2;

    cout << "t3 = " << t3 << endl;

    // operator-= demonstration
    t2 -= t;

    cout << "t2 = " << t2 << endl;
    // operator== demonstration
    cout << "Does t2 equal t now? " << boolalpha << (t2 == t) << endl;

    // operator+= demonstration, tests that subtraction was done properly, and
    // t3 = empty polynomial
    t3 += t;

    cout << "t3 = " << t3 << endl;

}

OLD实施文件:

#include "polynomial.h" //header
#include <stdlib.h>

// Default Constructor:the default is a 0-degree polynomial with 0.0 coefficient

Polynomial::Polynomial() {
    size = 0;
    head = new Term;
    head->coeff = 0;
    head->power = 0;
    head->next = head;
    head->prev = head;
}

// Copy Constructor

Polynomial::Polynomial(const Polynomial &p) {
    Term *pPointer = p.head;
    if (pPointer == NULL) head = NULL;
    else if (this != &p) {
        if (head != NULL) this->~Polynomial();
        head = new Term;
        head->coeff = 0;
        head->power = 0;
        head->next = head;
        head->prev = head;
        size = p.size;
        //copy rest of polynomial
        Term *thisPointer = head;
        while (pPointer->next != p.head) {
            pPointer = pPointer->next;
            double coeff = pPointer->coeff;
            int power = pPointer->power;
            // create new Term with data from Term in p
            Term *newTerm = new Term;
            thisPointer->next = newTerm;
            newTerm->prev = thisPointer;
            newTerm->coeff = coeff;
            newTerm->power = power;
            thisPointer = thisPointer->next;
            // checks for end of p to link head and last term
            if (pPointer->next == p.head) {
                head->prev = thisPointer;
                thisPointer->next = head;
            }
        }
    }
}

// Destructor

Polynomial::~Polynomial() {
    if (head != NULL) {
        while (head->next != head) {
            Term *thisPointer = head;
            head = head->next;
            remove(thisPointer);
        }
        head->next = head;
        head->prev = head;
        head->coeff = 0;
        size = 0;
    }
}

// degree: returns degree of polynomial
// Pre: none (an empty polynomial will return as a 0-degree)
// Post: the largest degree in the polynomial is returned as an int

int Polynomial::degree() const {
    return head->next->power;
}

// coefficient: returns the coefficient of the x^power Term
// Pre: none
// Post: the coefficient, if an x^power Term exists, is return. If 
//      an x^power Term doesn't exist, 0 is returned

double Polynomial::coefficient(const int power) const {
    Term *thisPointer = head->next;
    while (thisPointer->power != power && thisPointer != head) thisPointer = thisPointer->next;
    if (thisPointer == head) return 0;
    return thisPointer->coeff;
}

// changeCoefficient: replaces the coefficient of the x^power term
// Pre: none
// Post: if an x^power Term exists, its coefficient will be changed to 
//      newCoefficient. If not, an x^power Term with that coefficient will be inserted

bool Polynomial::changeCoefficient(const double newCoefficient, const int power) {
    if (head == NULL) *this = Polynomial();
    Term *thisPointer = head->next;
    // either finds value to be changed or stops before head, indicating need for insertion
    while (thisPointer->power != power && thisPointer->next != head)
        thisPointer = thisPointer->next;
    // finds proper location for insertion if cycled through list
    if (thisPointer->next == head) {
        thisPointer = head;
        while (thisPointer->next->power > power) thisPointer = thisPointer->next;
        insert(thisPointer->next, newCoefficient, power);
    }
    else if (newCoefficient == 0) {
        remove(thisPointer);
    } else thisPointer->coeff = newCoefficient;
    return true;
}

// insert: inserts an x^power Term with coefficient newCoefficient into the
//      polynomial, directly just before the pos Term
// Pre: the function is passed a nonzero newCoefficient and a pos Term that
//      exists in the polynomial
// Post: returns true if new Term was successfully inserted, returns false if
//      pre conditions are not met

bool Polynomial::insert(Term* pos, const double newCoefficient, const int power) {
    if (newCoefficient == 0) return false;
    Term *thisPointer = head;
    while (thisPointer->next != pos && thisPointer->next != head)
        thisPointer = thisPointer->next;
    // returns false if pos Term is not found
    if (size > 0 && thisPointer->next == head && pos != head) return false;
    // creates new term using parameters
    Term *newTerm = new Term;
    newTerm->power = power;
    newTerm->coeff = newCoefficient;
    // redirects pointers of adjacent Terms to include newTerm in polynomial
    newTerm->next = thisPointer->next;
    newTerm->prev = thisPointer;
    thisPointer->next->prev = newTerm;
    thisPointer->next = newTerm;
    size++;
    return true;
}

// remove: removes pos Term from polynomial
// Pre: pos Term exists in polynomial
// Post: returns true if pos Term was successfuly removed, if not returns false

bool Polynomial::remove(Term* pos) {
    Term *thisPointer = head;
    // finds term before one to be deleted
    while (thisPointer->next != pos && thisPointer->next != head) thisPointer = thisPointer->next;
    //returns false if pos term is not found
    if (thisPointer->next == head) return false;
    // redirects pointers of adjacent Terms around pos, removes pos
    thisPointer->next = thisPointer->next->next;
    thisPointer->next->prev->prev = NULL;
    thisPointer->next->prev->next = NULL;
    delete thisPointer->next->prev;
    thisPointer->next->prev = thisPointer;
    size--;
    return true;
}

// Overloaded <<: prints Cn * x^n + Cn-1 * X^n-1 + ... C1 * X + C0

ostream& operator<<(ostream &output, const Polynomial& p) {
    Polynomial::Term *thisPointer = p.head->next;
    if (thisPointer != NULL) {
        while (thisPointer != p.head) {
            if (thisPointer->coeff < 0) output << "-";
            else if (thisPointer->prev != p.head) output << " + ";
            if (abs(thisPointer->coeff) != 1) output << abs(thisPointer->coeff);
            if (abs(thisPointer->power) == 1) output << "x";
            else if(thisPointer->power != 0) output << "x^" << thisPointer->power;
            thisPointer = thisPointer->next;
        }
    }
    return output;
}

// Overloaded operator+

Polynomial Polynomial::operator+(const Polynomial &in) const {
    Polynomial out = *this;
    out += in;
    return out;
}

// Overloaded operator-

Polynomial Polynomial::operator-(const Polynomial &in) const {
    Polynomial out = *this;
    out -= in;
    return out;
}

// Overloaded operator==

bool Polynomial::operator==(const Polynomial &in) const {
    Term *thisPointer = head->next;
    Term *inPointer = in.head->next;
    while (thisPointer != head || inPointer != in.head) {
        if (thisPointer->power != inPointer->power || 
            thisPointer->coeff != inPointer->coeff) return false;
        thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return true;
}

// Overloaded operator!=

bool Polynomial::operator!=(const Polynomial &in) const {
    return !(*this == in);
}

// Overloaded operator=

Polynomial& Polynomial::operator=(const Polynomial &p) {
    if (*this != p) {
        this->~Polynomial();
        *this = p;
    }
    return *this;
}

// Overloaded operator+=

Polynomial& Polynomial::operator+=(const Polynomial &in) {
    Term *thisPointer = head;
    Term *inPointer = in.head;
    while (thisPointer->next != head || inPointer->next != in.head) {
        int power = inPointer->next->power;
        double coeff = inPointer->next->coeff;
        // if t > p, insert t in p
        if (power > thisPointer->next->power) {
            insert(thisPointer->next, coeff, power);
            thisPointer = thisPointer->next;
        }
        // if p power = t power, add 
        else if (power == thisPointer->next->power)
            thisPointer->next->coeff += coeff;
        if (thisPointer->next->coeff == 0) remove(thisPointer->next);
        // only advances t if p->next isn't larger than t->next
        if (inPointer->next->power <= thisPointer->next->power)
            thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return *this;
}

// Overloaded operator-=

Polynomial& Polynomial::operator-=(const Polynomial &in) {
    Term *thisPointer = head;
    Term *inPointer = in.head;
    while (thisPointer->next != head || inPointer->next != in.head) {
        int power = inPointer->next->power;
        double coeff = inPointer->next->coeff;
        // if t > p, insert t in p
        if (power > thisPointer->next->power) {
            insert(thisPointer->next, -coeff, power);
            thisPointer = thisPointer->next;
        }
        // if p power = t power, subtract 
        else if (power == thisPointer->next->power)
            thisPointer->next->coeff -= coeff;
        if (thisPointer->next->coeff == 0) remove(thisPointer->next);
        // only advances t if p->next isn't larger than t->next
        if (inPointer->next->power <= thisPointer->next->power)
            thisPointer = thisPointer->next;
        inPointer = inPointer->next;
    }
    return *this;
}

1 个答案:

答案 0 :(得分:3)

您可以将assign运算符函数实现为:

self

如果Polynomial& Polynomial::operator=(const Polynomial &p) { if (*this != p) { this->~Polynomial(); *this = p; } return *this; } 语句中的条件是if,这将导致无限递归,这就是您的用例。

这也是错误的,导致未定义的行为。

行后

true

对象已经死了。任何取消引用 this->~Polynomial(); 的尝试都会导致未定义的行为。

您可能希望使用copy and swap idiom来实现复制赋值运算符。