-4

Inside second extender class, when called method clone(s) value of field is changing.

Listing:

#include<iostream>
using namespace std;
class Set
{
public:
    Set(int min,int max)
    {
        num_bits=max-min+1;
        num_bytes=(num_bits+7)/8;
        elems=new int8_t[num_bytes];
        for(int i=0; i<num_bytes; i++)elems[i]=0;
        minElem=min;
        maxElem=max;
    };

    void add(int n)
    {
        int bit=n-minElem;
        elems[bit/8]|=(1<<(bit%8));
    };

    void del(int n)
    {
        int bit=n-minElem;
        elems[bit/8]&=~(1<<(bit%8));
    };

    bool has(int n)
    {
        int bit=n-minElem;
        return(elems[bit/8]&(1<<(bit%8)));
    }

    void print()//str
    {
        int i=0;
        do
        {
            cout<<(has(i+minElem)?"1":"0");
            i++;
            if(i%8==0)cout<<" ";
        }
        while(i<num_bits);
    }

    ~Set()
    {
        delete[] elems;
    };

public://rotected
    int num_bits,num_bytes,minElem,maxElem;
    int8_t *elems;
};

class ExSet:public Set{
    public:
    ExSet(int min,int max):Set(min,max){}
    ExSet(Set s):Set(s.minElem,s.maxElem){/*clone(s);*/}
    void clone(Set s){
    //for(int i=0;i<num_bytes;i++){int x=s.elems[i];cout<<elems[i]<<'='<<s.elems[i]<<'/';}
    };
};

main()
{
    char *p="ABCZabxyz";
    Set s('A','z');
    do s.add(*p);
    while(*++p!='\0');
    s.del('B');
    s.print();
    cout<<endl;
    for(char c='A'; c<='z'; c++)if(s.has(c))cout<<c;
    cout<<endl;
    //delete &s;
    ExSet es(s);
    for(char c='A'; c<='z'; c++)if(s.has(c))cout<<c;
};

Expected:

10100000 00000000 00000000 01000000 11000000 00000000 00000001 11
ACZabxyz
ACZabxyz

Get:

10100000 00000000 00000000 01000000 11000000 00000000 00000001 11
ACZabxyz
FGINQRVWghqrvw
Tim Zimmermann
  • 6,132
  • 3
  • 30
  • 36
dimk
  • 11
  • 4
  • Read about the [Rule of Three](http://stackoverflow.com/questions/4172722), and also pass complex objects by reference unless you particularly want to copy them. – Mike Seymour Oct 27 '14 at 18:06
  • This is correct details:
    When create child ExSet es(s); value of field is changing. If i cut off I//ExSet es(s); i see as expected.

    Can't editing my post, editor demand more details unstoppable((
    – dimk Oct 27 '14 at 18:10

3 Answers3

1

Your are copying an object without having a custom copy constructor specified. This fails because your Set class has a member that points to a heap object. That heap object must be copied by a customer copy constructor since it is not correctly copied by the compiler provided copy constructor.

Read about defining copy constructors and about deep vs. flat copies.

Silicomancer
  • 8,604
  • 10
  • 63
  • 130
0

I think your problem is here:

ExSet(Set s):Set(s.minElem,s.maxElem){/*clone(s);*/}

When you call constructor of the Set, you allocate new array:

elems=new int8_t[num_bytes];

and lose pointer to previous data. You should create a proper copy constructor or change existing one.

Nikolay K
  • 3,770
  • 3
  • 25
  • 37
0

The following line is the source of your memory problems.

ExSet(Set s):Set(s.minElem,s.maxElem){/*clone(s);*/}

When you execute

ExSet es(s);

a temporary copy of s is made in the call to the constructor of ExSet. When that temporary is destructed, it deletes the memory held by elems.

When s is destructed, the same memory is again deleted. That leads to undefined behavior. In your case, it produces wrong results. In other cases, the program might crash.

You can resolve this particular problem by using

ExSet(Set const& s):Set(s.minElem,s.maxElem){/*clone(s);*/}

However, for a proper fix, provide a copy constructor and a copy assignment operator in Set. To understand why, look up the Rule of Three.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270