Learning about new with classes

so i just finished learning about copy oonstructor and I'm now learning new and delete. And I'm very puzzled on why people would use a pointer when defining a class type. For example say I have already made a class called Animal.

Animal *pCat = new Animal();


What does this line do? what is the purpose of using pointers with classes?
and why would you want to use pointers with classes? Is pCat equal to the new memory location of the Animal constructor? I just don't understand why you would use a pointer with classes and why you would want to use new. Please enlighten me.
In the general case, raw pointers are not very useful:
http://www.LB-Stuff.com/pointers

However, smart pointers (e.g. std::unique_ptr) are very useful. For example, if you have a polymorphic class type and you don't know how many instances or of what kind you need until runtime, the best way to store the instances is in a std::vector<std::unique_ptr<Base>> - consider a game where there are multiple enemy types that spawn randomly.

If you aren't working with polymorphic types, just a std::vector<Enemy> is sufficient, no pointers of any kind needed.
Last edited on
Why was @LB's post reported?

That line declares a variable pCat which is of type Animal*, or pointer to Animal. Then it sets the value of that variable to the memory location of a newly allocated instance of Animal. The () signifies that you are explicitly initialising the instance using the default constructor, though it is optional.

Anyway, there are a few reasons that you might declare something as a pointer, rather than just a normal object. The most common I can think of is polymorphism; that is, if you have derived classes which you may want to store in the object:
1
2
3
4
5
6
7
8
class Animal {};
class Cat : public Animal {};
class Dog : public Animal {};

// ...

Animal *pCat = new Cat;
Animal *pDog = new Dog;

For example, in the above code I have two classes, Dog and Cat that are types of Animals. In that case, I can happily pass them to a function that only accepts an Animal as a parameter, and everything would work fine.

If you want an array of classes, then you have to use a pointer to declare the variable. In this case you need to use the appropriate operator, new[]. Of course, it is generally better to use some kind of wrapper such as std::vector rather than doing your allocation manually.

Some other options for why using pointers when declaring classes can be helpful include when you are modifying a class that doesn't belong to that function (e.g. it has been passed as a function parameter), or if you want to be able to 'disable' the variable (e.g. set the value of the variable to nullptr to suggest that there is no Animal there). Note that there are typically better options for the above, though.
There are at least three semi-independent topics here.

First, the pointer. Pointer is a type that has two primary properties:
1. The value stored by a pointer object is a memory address.
2. Pointer has dereference operator that allows accessing an object at a memory address.

Example:
1
2
3
int foo {42};
int * bar {&foo};
std::cout << *bar; // same as std::cout << foo; 

Both raw pointers and smart pointers are pointers.

Pointers allow indirection. Crude example:
1
2
3
4
5
6
7
8
9
10
int gaz( int lhs, int rhs, bool left ) {
  int result {nullptr};
  if ( left ) {
    result = &lhs;
  } else {
    result = &rhs;
  }
  // do something with *result
  return *result;
}



Then the new:
This is dynamic memory allocation. A "normal variable" object is allocated statically from stack memory and has lifetime of its enclosing scope. Dynamic allocation creates object in free store memory and object remains alive until it is explicitly destructed. Like the pointer indirection example, we usually do not know during compilation whether user input will demand creation of one Cat or nine Dogs, so static allocation is not possible. Furthermore, the free store has more memory than the stack on most systems, so big data has to use free store.

The new, std::make_unique and std::vector all do dynamic allocation. The crucial difference is in how the deallocation has to (or will) be invoked.


using pointers with classes

Red herring. The C++ language does not have many types and they are all simple. The class syntax allows definition of additional (more complex) types. Classes are not special; they are just types The more proper question is thus: "using pointers with types".

The features of pointers gives a part of the answer.

The memory address of dynamically allocated object is not known during compilation. The address is determined when the program is running. There is no way to access the object, unless the address is stored somehow.

The others have already mentioned the polymorphism. When a type is defined not from scratch but by reusing and expanding existing type definition (the class inheritance syntax), then the types have special relation that can be exploited.

The C++ Standard Library provides a collection of useful class definitions, so the users do not have to do everything themselves.


Animal *pCat = new Animal();
Declare a (static) pointer variable.
Initialize the variable with the address of dynamically allocated object.
Construct an Animal object with its default constructor within the dynamically allocated memory.
Topic archived. No new replies allowed.