Terminology:
- A default constructor is a constructor that can be called with no arguments. For instance: - class A { A() { /* ... */ } };
class Point { Point(int x = 0, int y = 0) { /* ... */ } };
 
- A copy constructor is a constructor whose "first parameter is of type - X&,- const X&,- volatile X&or- const volatile X&, and either there are no other parameters or else all other parameters have default arguments". For instance:
 - class A { A(const A& other) { /* ... */ } };
class Point { Point(Point& other, int x = 0) { /* ... */ } };
 
If your class declares no constructor, the compiler will implicitly define a default constructor for you. The implicitly defined default constructor performs only very basic initializations:
- Any base-class subobject is default-constructed;
- Any member of class type is default-constructed;
- No initialization is performed for class members of scalar type (int,double, pointers, etc.)
If any of the above is impossible  (for example, a member of class type has no default constructor), then the compiler will report an error.
If your class does not declare a copy constructor, one is implicitly declared. If a move constructor or move assignment operator is declared, the copy constructor is declared as deleted and any attempt to use it will result in a compiler error. Otherwise, the implicitly declared copy constructor performs a memberwise copy.
Second, unlike Java, C++ objects have value semantics. When you write Animal animal; in Java, animal is a reference to an Animal object and is initialized to a null reference. When you write Animal animal; in C++, animal is an Animal object.  When you write Animal animal2 = animal; in Java, animal2 and animal refer to the same Animal object, and you just copied the reference. When you write Animal animal2 = animal; in C++, animal2 is a copy of animal created using the copy constructor. They are distinct Animal objects. (The Java equivalent for this is clone().)
Further, new in C++ and in Java are very different things. In Java, new is how you create an object. In C++, as noted above, we don't need new to create an object. Rather, new means "allocate memory on the heap, construct the object in that memory, and return a pointer to it, which I'll free with delete when I'm done". new Animal() doesn't return an Animal, it returns an Animal * - a pointer to an Animal. Thus, something like animals[0] = new Animal(); will never compile without some horrible hackery, and even if you somehow made it compile, you've lost the pointer returned by new, so you cannot delete it, which means that you now have a memory leak. It's just terrible C++ code. Don't do it.
Now, when you define an array in C++ without an initializer:
Animal animals[10]; 
You create an array of 10 Animal objects, not 10 references to Animal objects. Each member of the array is default-constructed. If Animal does not declare (explicitly or implicitly) a default constructor, you'll get a compiler error. The exact initialization performed depends on the default constructor; if you use the implicit one, then scalar class members will have indeterminate values and attempting to read the value results in undefined behavior.
The proper way of ensuring that default-constructed Animals do not have uninitialized members is to simply write your own default constructor that performs the necessary initialization:
class Animal {
public:
    Animal() : m_name("none"), m_legs(0) { }
private:
    std::string m_name;
    int m_legs;
};
This default constructor initializes the name of the animal to the string "none" and the number of legs to 0.
Arrays in C++ do not carry their size information with them. There are several ways to get around this:
- Use the std::arrayclass, which provides asize()member function, instead of a plain array. Instead ofAnimal animals[10];, writestd::array<Animal, 10> animals;.  Then you can get the size withanimals.size(). This is the best way by far.
- Calculate the size of the array with sizeof(animals) / sizeof(animals[0]). This would not work if you passanimalsto another function (unless the function is written in a very special way), since arrays will decay to pointers at the drop of a hat, and callingsizeofon a pointer won't give you the array's size.
- Store the size as a constant: const int szAnimals = 10; Animal animals[szAnimals];.