T* represents a pointer type, which represents a variable that contains a "reference" (usually a memory address) to some instance of type T. Using a real world comparison, a T* pointer stands to T like a street address stands to a building.
Pointers allow you to refer to some instance owned by some other variable, and you can use a valid, non null instance of T* to read and write on a T. In this, they are similar to another C++ concept, references (written as T&), which allow you to alias variables, but differ significantly from pointers by not being objects in their own regard.
A pointer is, in fact, an object itself, with each pointer variable having its own unique address and being thus storable and referenceable. For instance, you can have pointers to pointers (T**) and references to pointers (T*&), but not pointers to references - pointers exist, while references may not (they are usually implemented as pointers underneath though).
To reflect the this "indirect" nature of pointers, C and C++ provide you with two different operators which allow you to dereference a pointer (* and ->), and to reference a variable (&).
For instance, you may do the following:
struct A { int x; };
// ...
A a {};
A *aptr { &a }; // `&` takes the address of `a` and stores it into the `aptr` variable of type `A*`
aptr->x = 33; // `->` is equivalent here to `(*aptr).x`, a.x is now 33
A a2 {};
A **aptrptr { &aptr }; // pointer to pointer
*aptrptr = &a2; // `aptr` now points to `a2`
operator-> is basically syntactic sugar that avoids you some cumbersome expressions like (*aptr).x.
References, being basically just aliases to something else, do not need any special syntax at all, and are always converted transparently when neeeded:
int x { 33 };
int &xref { x }; // `xref` refers to `x`
xref = 12; // `x` is now 33
int y = xref; // copies `x` into `y`, no special syntax needed
Pointers are also used in the C language to access arrays, which always decay to a pointer as soon as they are referred to in expressions. This is messy and it's one of the reasons std::vector and std::array should always be used in their place when feasible.
int x[33];
x[3] = 44; // equivalent to `*(&x[0] + 3) = 44`
Finally, the "indirect" nature of pointers and references allow C++ to convert a Derived* to a Base*, given that a derived class contains a full instance of its base (it gets more complicated with multiple inheritance though).
Every class that inherits or contains from another class containing virtual methods will include a hidden pointer to a _Virtual Method Table`, a list of pointers to functions which will be used to dispatch the virtual methods to the correct implementation.
PS: in modern C++, you should rarely need raw pointers. The correct approach is to use containers such as std::vector, std::array and std::string, and special pointer-like wrappers called smart pointers (like std::unique_ptr) every time you need a pointer for some reason. These will handle the lifetime of a pointer for you, avoiding memory leaks and vastly simplifying memory handling. For the same reason, the new operator should be mostly considered as being deprecated and should not be used at all (unless in placement new expressions, are potentially dangerous if used improperly).