3

I have a question about user defined conversion.

class String {
    char* m_data;

public:
    String(): m_data(NULL) {}
    String(const char* cstr): m_data(new char[strlen(cstr)+1]) {
        strcpy(m_data, cstr);
    }
    ~String() {
        delete[] m_data;
    }
    String& operator=(const char* cstr) {
        delete[] m_data;
        m_data = new char[strlen(cstr)+1];
        strcpy(m_data, cstr);
        return *this;
    }
    operator const char*() const { 
        return m_data;
    }
};

While this works:

int main(int argc, char** argv) {
    String a;
    String b;
    a = "aaa";
    b = (const char *)a;
    return 0;
}

This does not:

int main(int argc, char** argv) {
    String a;
    String b;
    a = "aaa";
    b = a;
    return 0;
}

I get double free or corruption runtime error. Valgrind says something about invalid delete.

Why do I have to explicitly typecast it? I thought it would work this way with explicit operator const char*(). Am I doing something wrong?

NefariousOctopus
  • 807
  • 2
  • 10
  • 18

1 Answers1

7

You forgot to define copy assignment operator:

String& operator=(const String& other) {
    if(this != &other) {
        char* new_data = new char[strlen(other.m_data)+1];
        strcpy(new_data, other.m_data);
        delete[] m_data;
        m_data = new_data;
    }
    return *this;
}

Because of that your compiler had to define "default" copy assignment operator, which simple assigns all fields of "other" to a current object:

String& operator=(const String& other) {
    m_data = other.m_data;
    return *this;
}

So you have two pointers to same m_data in a and b and on the exit from main, delete[] will be called twice.

T.C.
  • 133,968
  • 17
  • 288
  • 421
myaut
  • 11,174
  • 2
  • 30
  • 62