Uploaded by alamriturki00

C Pointers

advertisement
C++ Pointers
Made by:
Turki Alamri
Adel AlHarbi
Fawaz Alanzi
Aouf Alsayed
Mouthanna Alsharif
under the supervision of Dr:
Hassan Aleraqi
Keywords:
-
Pointers
Raw Pointers
Const and Volatile Pointers
New and Delete Operators
Smart Pointers
Function Pointers
Abstract:
When we declare a variable in C++, a specific location
in memory is assigned to it to store a value in this
variable. This location is called the memory address of
the variable. Pointers in C++ are special variables that
store the memory address of other variables. Pointers
add more features and flexibility to the C++
programming language.
Introduction:
C++ is one of the simplest and most common programing languages
that provides the programmer with a good using experience, it has
many tools to choose from and one of them being pointers.
Pointers are used usually in both C and C++ for 3 main purposes:
• passing functions to other functions
• allocating new objects on the heap,
• iterating over elements in data structures.
Raw pointers:
The pointer whose lifetime isn't controlled by an encapsulating
object is raw pointer, such as a smart pointer. A raw pointer can be
assigned the address of another variable which is non-pointer, or it
can be assigned a value of nullptr. When the pointer hasn't been
assigned a value, it contains random data.
When allocating an object on the heap in memory by a program,
the heap receives the address of that object in the form of a pointer.
Such pointers are called owning pointers. An owning pointer (or a
copy of it) must be used to explicitly free the heap-allocated object
when it's no longer needed. When fail to free memory, it results in a
memory leak and makes that memory location unavailable to any
other program on the machine. allocated memory which uses new
must be freed by using delete (or delete[]).
When pointer is not declared as const, it can be incremented or
decremented to point at another location in memory. This operation
is called pointer arithmetic. It's used in C-style programming to
iterate over elements in data structures.
Const and volatile pointers:
Const and volatile pointers have specific uses in C++. The const
keyword is used to specify that a pointer cannot be modified after
initialization. This means that the value it points to is protected from
any modifications. On the other hand, the volatile keyword is used
to indicate that the value associated with a name can be modified by
actions outside of the user application. This is particularly useful for
objects in shared memory that can be accessed by multiple processes
or for global data areas used in communication with interrupt
service routines.
When a name is declared as volatile, the compiler reloads the value
from memory every time it is accessed. This prevents certain
optimizations, but it ensures predictable program performance
when the state of an object can change unexpectedly.
To declare a const or volatile object pointed to by a pointer, the
syntax is as follows:
To declare a const or volatile value of the pointer itself (the address
stored in the pointer), the syntax is:
new and delete operators:
The new operator:
The compiler translates a statement like this one into a call to the
function operator new:
If the request is for zero bytes of storage, operator new returns a
pointer to a distinct object. That is, repeated calls to operator new
return different pointers.
If there's insufficient memory for the allocation request, operator new
throws a std::bad_alloc exception. Or it returns nullptr if you've used
the placement form new(std::nothrow), or if you've linked in nonthrowing operator new support.
Scope for operator new functions
The global operator new function is called when the new operator is
used to allocate objects of built-in types, objects of class type that
don't contain user-defined operator new functions, and arrays of
any type. When the new operator is used to allocate objects of a class
type where an operator new is defined, that class's operator new is
called.
The delete operator:
The delete operator calls the operator delete function, which frees
memory back to the available pool. Using the delete operator also causes
the class destructor (if one exists) to be called.
There are global and class-scoped operator delete functions.
Two forms exist for the global operator delete and class-member
operator delete functions:
The first form takes a single argument of type void *, which contains a
pointer to the object to deallocate. The second form, sized deallocation,
takes two arguments: the first is a pointer to the memory block to
deallocate, and the second is the number of bytes to deallocate. The
return type of both forms is void (operator delete can't return a value).
The intent of the second form is to speed up searching for the correct size
category of the object to delete. This information often isn't stored near
the allocation itself, and is likely uncached. The second form is useful
when an operator delete function from a base class is used to delete an
object of a derived class.
Smart pointers (Modern C++):
In modern C++ programming, the Standard Library includes smart
pointers, which are used to help ensure that programs are free of
memory and resource leaks and are exception-safe.
Uses for smart pointers:
Smart pointers are defined in the std namespace in the header file.
They are important to the RAII or Resource Acquisition Is
Initialization programming idiom.
The main goal of this idiom is to make sure that resource acquisition
happens at the same time that the object is initialized, so that all
resources for the object is made ready in one line of code.
In a lot of cases, when you initialize a raw pointer or resource handle
to point to an actual resource, pass the pointer to a smart pointer
immediately.
In modern C++, raw pointers are only used in small code blocks of
limited scope, loops, or helper functions where performance is critical
and there is no chance of confusion about ownership.
A smart pointer is a class template that you declare on the stack and
then initialize by using a raw pointer that points to a heap allocated
object.
After the smart pointer is initialized, it basically owns the raw
pointer. This means the smart pointer is the one responsible for
deleting the memory that the raw pointer specifies.
Access the encapsulated pointer by using the familiar pointer
operators, -> and *, which the smart pointer class overloads to return
the encapsulated raw pointer.
Function Pointer in C++:
The function pointer is a pointer which main use is to point functions.
Its main purpose is to store the address of a function. We can call the
function by using the function pointer (sometimes referred as funcptr)
or we can also pass the pointer to another function as a parameter.
They are mainly useful for event driven applications and callbacks and
even for storing the functions in arrays.
The computer only understands the low-level language, i.e., binary form.
The program we write in C++ is always in high-level language, so to
convert the program into binary form, we use compiler.
The compiler source code into an executable file then the executable file
gets stored in the RAM. The CPU starts the execution from the int main()
method and it reads the copy in RAM but not the original file.
All the functions and machine code instructions are data and these data is
a bunch of bytes and all these bytes have some address in RAM. The
function pointer contains the RAM address of the first instruction of a
function.
Syntax for Declaration:
here in the following is the syntax for the declaration of a function pointer:
Here in this syntax, we supply the return type, and then the name of the
pointer, i.e., FuncPtr which is surrounded by the brackets and preceded
by the pointer symbol, i.e., (*). After this we have fill the parameter list
(int,int). The above function pointer can point to any function which takes
two integer parameters and returns integer type value.
Therefore, the name of the function itself without any brackets or
parameters means the address of a function. We can still use an alternative
way to print the address of a function, i.e., &main.
Address of a function:
We can get the address of a function easily by mentioning the name of
the function without having to call the function, An example.
In the above program, we are displaying the address of a main()
function. To print the address of a main() function, we have just
mentioned the name of the function, there is no bracket not parameters.
Therefore, the name of the function by itself without any brackets or
parameters means the address of a function. We can use the alternate
way to print the address of a function, i.e., &main.
Calling a function indirectly :
We can call the function with the help of a function pointer by
simply using the name of the function pointer. An example.
In the above program, we declare the function pointer, i.e., int
(*funcptr)(int,int) and then we store the address of add() function in
funcptr. This implies that funcptr contains the address of add()
function. Now, we can call the add() function by using funcptr. The
statement funcptr(5,5) calls the add() function, and the result of add()
function gets stored in sum variable.
Passing a function pointer as a parameter:
The function pointer can be passed as a parameter to another
function, An example.
In the above code, the func2() function takes the function pointer as a
parameter. The main() method calls the func2() function in which the
address of func1() is passed. In this way, the func2() function is calling
the func1() indirectly.
Conclusion:
Some Common Mistakes to Avoid with Pointers in C++:
here are a few important common mistakes that should be avoided
while using pointers.
•
Not Initializing Pointers: When you declare a pointer variable,
it does not point to a specific memory address automatically.
•
Dangling Pointers: A dangling pointer is a pointer that points to
a memory location that has been freed or erased. This can lead the
program to undefined behavior or even a crash.
•
Forgetting to Dereference Pointers: it means accessing the value
stored at the memory address pointed to by the pointer. If you forgot
to dereference a pointer it can result in errors or unexpected behavior.
•
Not Checking for NULL Pointers: NULL pointers are pointers
that do not point to any valid memory address. If you try to access the
value stored at a NULL pointer, you will get a segmentation
fault(access violation).
•
Memory Leaks: Memory leaks occur when you allocate memory
dynamically using functions like malloc() or new but fail to deallocate
it when it is no longer needed. This can lead to a shortage of memory,
causing the program to crash.
Conclusion (Continued) :
In summary, pointers are a powerful tool in C++ programming that
allows for dynamic memory allocation and manipulation of data
structures. While they can be tricky to use correctly, understanding
how pointers work and being extra careful with memory
management can lead to efficient and effective code.
It is important to remember to always initialize pointers, avoid
dangling pointers, and properly deallocate memory to avoid memory
leaks. With proper usage and care, pointers can be an invaluable asset
to any C++ programmer.
Resources:
C++ Pointers by Microsoft [2021]
Pointers in C++ by Scaler Topics [2023]
Pointers in C++ by Shivani Goyal [2020]
Function Pointers in C++ by java point [2021]
Download