Category: Proxy usage
How do I invoke the Java default constructor?
You have to pass the "dummy" argument _use_java_ctor, for example:
Vector v( _use_java_ctor );
Why do we have this unexpected requirement? In Java, the circumstances surrounding object creation are much simpler:
- all objects live on the Java heap
- all objects are created when a constructor is called as part of a new invocation.
C++ has a much richer and more difficult model:
- objects can be dynamically allocated on the C++ heap via operator new().
- objects can be stack-allocated and automatically destroyed when the current stackframe goes out of scope
- objects can be globally allocated
- objects are copied under certain circumstances.
- in general, memory allocation and object instantiation are more loosely coupled.
- the C++ default constructor is invoked by the compiler under all kinds of circumstances.
This last point is the point that finally drove us to requiring a dummy argument when invoking the Java default constructor. Let's assume for a moment that we did not have this requirement and that the C++ default constructor were tied to the Java default constructor. What do you think would happen in the following snippet:
1: HugeMemoryConsumer hmc; 2: 3: if( myCondition == true ) 4: hmc = ObjectFactory::get_a_HugeMemoryConsumer(); 5: 6: HugeMemoryConsumer sparseArray[ 1000 ]; 7: 8: sparseArray[ 513 ] = hmc;
In the above snippet, we have a proxy type for a Java type called HugeMemoryConsumer, which as the name indicates, consumes huge amounts of memory per instance. In line 1 we declare an instance of this type and in line 4 we assign a value to it.
The problem is that, in C++, line 1 already invokes the default constructor! This means that you unintentionally created a Java instance consuming a huge amount of memory. It's even worse in line 6: C++ will invoke the default constructor on every single instance in the array. This means that you would end up with an array holding 1,000 instances, when all you wanted was to assign a single instance to one element and have the others be null.
This is of course a heavily construed example, but it demonstrates why we wanted to make object creation an explicit act rather than a compiler-invoked act.