简体   繁体   中英

C++ Copy Constructor Strange Behavior

Given the following code:

class monomial {
public:
    mp_real coe;
    int exp;        
    monomial *next; 
};

class polynomial  
{  
private:
    monomial *start;
public:
    polynomial();
    ~polynomial();
    void destroy_poly(monomial *);
    polynomial & operator=(const polynomial &);
    polynomial(const polynomial&);
    monomial * get_start();
};  
polynomial::polynomial() {
    start = NULL;
}
polynomial::~polynomial() {
    if (start != NULL) {
        destroy_poly(start);
    }
    start = NULL;
}
void
polynomial::destroy_poly(monomial * m) {
    monomial * cm = m;
    if (cm->next != NULL) {
        destroy_poly(cm->next);
    }
    delete m;
}
polynomial::polynomial(const polynomial& p) {
    if (p.start != NULL) {
        start = new monomial();
        start->coe = p.start->coe;
        start->exp = p.start->exp;

        monomial * tmpPtr = p.start;
        monomial * lastPtr = start;

        while (tmpPtr->next != NULL) {
            monomial * newMon = new monomial();
            newMon->coe = tmpPtr->next->coe;
            newMon->exp = tmpPtr->next->exp;

            lastPtr->next = newMon;
            lastPtr = lastPtr->next;
            tmpPtr = tmpPtr->next;
        }
    }
}
polynomial & polynomial::operator=(const polynomial &p) {
    if (p.start != NULL) {
        start = new monomial();
        start->coe = p.start->coe;
        start->exp = p.start->exp;

        monomial * tmpPtr = p.start;
        monomial * lastPtr = start;

        while (tmpPtr->next != NULL) {
            monomial * newMon = new monomial();
            newMon->coe = tmpPtr->next->coe;
            newMon->exp = tmpPtr->next->exp;

            lastPtr->next = newMon;
            lastPtr = lastPtr->next;
            tmpPtr = tmpPtr->next;
        }
    }
    return *this;
}

Then in main.cpp:

main() {
    polynomial poly;
    // code that initializes / sets values for 
    // various monomials pointed to by poly.start.

    map<set<unsigned int>, polynomial> hash;
    set<unsigned int> tmpSet;

    tmpSet.insert(0);

    hash[tmpSet] = poly;
}

I can set a breakpoint on the first line of the copy constructor, and after I step-over the hash[tmpSet] = poly line, p.start inside the copy constructor is NULL. Then, it gets called a second time, at which time p.start has strange values set inside it.

Any clue what is going on?

Thanks, Erich

EDIT 1: Thought adding the assignment operator to the polynomial class fixed it, but it did not. Still having the same problem.

You are violating the Rule of Three :
Since you overload Copy constructor , You Should overload copy assignment operator and destructor for your class.

The above statement was in reference to general scenarios, In your code example, you can replace the should with a must .

Two issues.

1) You don't have a no-argument constructor, so the compiler is filing in the initial values as it sees fit. The fact that p.start is initially NULL is

2) When your copy constructor passed a polynomial with p.start == NULL , you don't initialize any of the variables in the class, so the next copy could have whatever initial value the compiler assigns (see problem #1).

To fix, you should add a no-arg constructor that initializes the polynomial into a sane state. And then the copy constructor, if passed such a polynomial, should initialize itself to a sane state.

You should add a default constructor, where you initialize start to NULL.

As Als pointed out, you violating the Rule of Three. Well look, when you put something in container what happens to your pointers.

monomial *start;
monomial *next;

Think about this.

Your copy constructor leaves start set to some random value if p.start == NULL. That might be the cause of the problem, depending on other code in your program. Also, you have no assignment operator, so the compiler is doing shallow copies for you. You have to add another function polynomial &operator=(const polynomial& b)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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