Very basically, in untyped languages, every reference point to an object that contains both the type and the value. For example var a = 3
points to an instance that contains the value 3 and the type int, if you make a = "bla"
, the reference is updated to an instance that contains the string "bla" and the type string, the old object is discarded, etc...
This is slow because every time an operation (eg a + b
) must be made on these basic type, the runtime must first dereference the objects, check that their type are compatible, perform the operation, create a new object.
In contrast, a + b
in C++ or Java checks at compile time that the types are valid and compatible, then a and b are stored as immediate values (not references), and the addition is a simple processor operation on these values.
Of course, this is all very theoretical. In practice, a lot of optimization can be done on this process to avoid most of the overhead, and dynamically typed languages can get quite fast.