我在我的代码中发现了一个错误,其中包含我的驱动程序中的行
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;
}
答案 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来实现复制赋值运算符。