c++ initialize other class in constructor

139 Views Asked by At

Ok, so there's something I can't understand with the c++ constructor:

If I use the initializer list method, the code works:

Client::Client() : id(), name(){
    // this works!
}

But the regular method doesn't:

Client::Client(){
    id = String();
    name = String();
    // does not work
}

String is just another class I wrote; The String default constructor is as follows:

String::String(){
    str = NULL;
}

Afaik, initializer lists allow you to initialize consts and references, but I dont really see how it helps here?

What am I missing?

EDIT: declarations:

class String {
    char *str;
public:
    String();
    String & operator =(const String &rhs);
}

class Client {
    String id, name;    
public:
    Client();   
};

String does have an assignment operator but I want to use it to copy the contents of "str" into the lhs String, could this be the problem? as in it tries to use my assignment operator and fails?

SOLVED:

Ok, It is indeed the assignment operator, it seems that if I give it a String with str = NULL, it fails to strcpy and stops the program. Sorry for not being accurate, I did try to debug and found out it failed @ the constructor of client when I try to initialize the String vars as I have more code coming after that. So I understand that the 1st method of initialization works because it just straight up does not use the assignment operator.

String & String::operator =(const String &rhs){
    /*if(!rhs.str){ return *this; }*/ // had to add this line!
    str = new char[strlen(rhs.str)];
    strcpy(str, rhs.str);
    return *this;
}

Thank you guys a bunch.

Thanks ahead, Michael.

2

There are 2 best solutions below

3
On

it fails to strcpy and stops the program

Well, there's your bug. In the line id = String(); you call the copy assignment with a String with null str member as the parameter. Your copy assignment operator apparently tries to strcpy from the null pointer which has undefined behaviour.

Best advice that I can give you is "use std::string".

So I understand that the 1st method of initialization works because it just straight up does not use the assignment operator, is that correct?

Correct. Both versions default construct the members first, but the second one does copy assignment as well. You don't need to have a user defined constructor at all for Client if default initialization is sufficient.

0
On

The difference between these two constructor implementations is that the former explicitly default-constructs the elements, whereas the second does so implicitly, then calls the assignment operator on a default-constructed instance.

Client::Client() : id(), name(){
}

Client::Client(){
    id = String();
    name = String();
}

If your assignment operator is broken, then the first version will work and the second won't.

You should always prefer to initialize in the initialization-list to doing so in the constructor body, as the latter will result in an unnecessary construction, then an assignment.