The C++ standard refers to the term "dynamic type" (and the C standard refers to "effective type" in the similar context), for example
<
The status quo is that malloc
does not create objects. The only constructs that do are new
expressions, definitions, casts and assignments to variant members. See P0137R0 for proper wording on this.
If you wanted to use the storage yielded by malloc
, assuming that it is properly aligned (which is the case unless you use extended alignments), employ a call to placement new:
auto p = malloc(sizeof(int));
int* i = new (p) int{0};
// i points to an object of type int, initialized to zero
Hence using malloc in C++ is quite useless, as bog-standard new
effectively combines the above steps into one.
See also @T.C.'s answer in the related question of the asker.
According to the C++ specification:
Dynamic type:
<glvalue> type of the most derived object (1.8) to which the glvalue denoted by a glvalue expression refers
The return value of malloc
is a block of uninitialized storage. No object has been constructed within that storage. And therefore it has no dynamic type.
The void*
does not point to an object, and only objects have a dynamic type.
You can create an object within that storage by beginning its lifetime. But until you do so, it's just storage.
Dynamic type is a formal term to describe essentially polymorphic objects i.e. ones with at least one virtual
function. It is thus a C++ term as C has no concept of virtual
, for example.
But how is the dynamic type of the object allocated with malloc determined?
It isn't. malloc
allocates N
raw bytes of memory and returns it through a void*
- it's your job to infer the right type. Moreover, this memory just represents the area where the object is placed, but this object will not be alive till you explicitly call its constructor. (again, from a C++ perspective)
Will the dynamic type of the object pointed to by pi be int?
No, because the term dynamic type is meaningful when describing object with class types. int
is not nor can be.
class Foo
{
//virtual ~Foo() = default;
virtual void f() {}
};
class Bar : public Foo
{
virtual void f() {}
};
// ...
Foo *ptr = new Bar();
Here Foo
is the static type of ptr
while Bar
is its dynamic type.
As per 1.3.7 in C++11 standard,
dynamic type glvalue type of the most derived object (1.8) to which the glvalue denoted by a glvalue expression refers [Example: if a pointer (8.3.1) p whose static type is “pointer to class B” is pointing to an object of class D, derived from B (Clause 10), the dynamic type of the expression *p is “D.” References (8.3.2) are treated similarly. — end example ]
for an example
class A {}
class B : public A {}
A *a = new B;
the "static" type of a
is A *
while its dynamic type is B *
.
The idea of referencing not the same type comes to protect from something like
class A{}
class B : public A {int x;}
class C : public A {int y;}
A *a = new B;
reinterpret_cast<C *>(a)->x;
which may lead to undefined behavior.
void *
does not point to an object, but the distinction between dynamic and declaration type makes sense only for objects.
In C, the effective type is only relevant when you access an object. Then in is determined by
memcpy
)void*
is converted to another pointer type (e.g int*
), which then is dereferenced.The latter is usually what happens with malloc
ed objects, if you assign the return value of malloc
to a pointer type.