In some cases, you may need to initial all variables of a class, so you'll use a constructor to assign values for all, in other cases you may want to initial some variables of that class but not all, so you have to simplify your class initialization by adding multi constructors
if you have a class called Person, it takes in the constructor (string name, int age, string city), when you initial Person class you do:
Person p = new Person(John, 41, Sitka);
what if you want only to put the person name?
you have to make smaller constructor of Person class that will take only the person name, and will fill the remain variables with some default values whether by filling the variables directly or by filling them through the bigger constructor by using (this) keyword:
this(name, 0, null)
Multiple constructors get used when you want to input varying amounts of initial data for an object. That way you can have a constructor that gives default values and one that accepts user-defined values.
This is known as overloading. If someone were to call the constructor without any parameters while the only constructor you have is WITH parameters then you are going get into trouble. Basically you give flexibility to your program by allowing the user to call the constructor in more than one ways
The constructor is the way to have every object determine its initial value. When you create a new object in C++, initially all of its data members have a completely indeterminate value. If you want to have the object determine its own default, it needs to have some code to execute in order to set its fields to meaningful values. So in short, yes, objects should determine their initial values, and the constructor is the way to do it. They're invoked automatically, and so from a client's perspective there's no need to explicitly invoke any initialization routines. The constructor does this automatically.
As for the default constructor, it can and often does have code in it that makes it very different from nothing. A vector constructor, for example, might set up a pointer to a small buffer where the elements can be stored, as well as recording the size of the object as zero. Doing nothing would leave the pointer pointing somewhere randomly in memory and with the size fields set to garbage, violating the class invariants and rendering the object unusable.