Section 24 : C++ 11
Auto
- When we don't know the data type that we require or it depends on the result, then we can declare it as
auto. - Example:
- We can use
autowhen we are calling a function and we don't know what the return type of that function is.
decltype
* One more feature of C++11 is when we want to copy the data type of another variable but we don't know its data type, but we have the variable name, then we can use decltype function.
z will be the same as the data type of y.
* Variable z will be of float type because y is of float type.
Final Keyword
- One usage of
finalis to restrict inheritance. - If we declare a class as
finalthen it can't be inherited. - Virtual Functions: Only virtual functions can be marked as
final. - The
finalfunction of a parent class cannot be overridden in the child class.
classDiagram
note "Concept of Final Keyword"
class Parent {
virtual void show() final
}
class Child {
void show() -- Cannot Override
}
Parent <|-- Child : Inheritance
- Summary:
finalkeyword is used in C++ for restricting inheritance as well as restricting overriding of functions. - Comparison: Same feature is available in Java also. The only difference is the
finalkeyword is used before the return type of a function in Java, whereas in C++ it is written after the name of a function or after the parameter list.
Lambda Expressions
- It is useful for defining unnamed functions.
- Syntax:
Examples:
-
Define and call a function to print "Hello":
-
With parameters:
- For calling:
- With return type:
- I don't have to mention the return type, because C++ supports
autotype deduction. So automatically, whatever the data type is, that data type is returned.
-
Assigning to a variable: Instead of calling the function immediately, we can assign it to an
autovariable. -
Explicit Return Type: If we want to mention the return type (optional):
Capture List:
- We can access the local variables of a function inside an unnamed function (lambda), but we need to capture them using
capture_list. - By Value: If we want to access all things in scope by value, write
=. -
Note: We cannot modify captured variables by value directly (e.g.,
a++won't work unlessmutableis used, or captured by reference). -
By Reference: If we want to access all things in scope by reference, write
&. - To modify captured variables, we usually use reference.
Applications:
- We can send a lambda expression to a function as a parameter.
- Lambda expressions are very flexible for defining the scope of a function within a line or block of statements. Helpful for nested functions.
- This is a feature of functional programming often used in AI.
Smart Pointers
- Pointers are used for accessing resources external to the program, like Heap Memory.
- The Problem: With standard heap memory, we must manually deallocate it. If we forget, it causes Memory Leakage.
- Solution: C++ provides smart pointers which automatically manage memory. When the pointer goes out of scope, it automatically deallocates the memory.
- Defined in header:
#include <memory>
graph TD
A[Smart Pointers] --> B[unique_ptr]
A --> C[shared_ptr]
A --> D[weak_ptr]
B --> B1[Strict ownership<br>Cannot be shared]
C --> C1[Reference Counting<br>Shared ownership]
D --> D1[No Reference Count<br>Prevents Deadlocks]
1. unique_ptr
-
Instead of
Rectangle *p = new Rectangle(10, 5);, we write: -
unique_ptrtakes care of deletion when it goes out of scope. - Only one pointer can point to the object. We cannot share the object with another pointer.
- We can transfer control to another pointer using
std::move, removing the first pointer.
2. shared_ptr
-
Syntax:
-
More than one pointer can point to the same object.
- It maintains a Reference Counter (
ref_counter) to track how many pointers are pointing to the object. - We can check the count using
p1.use_count().
3. weak_ptr
-
Same as shared pointer, but it will not maintain a reference counter.
-
It holds a "weak" reference. It does not have a strong hold on the object.
- Use Case: If pointers hold objects and request others, they may form a deadlock. Weak pointers are useful to avoid circular dependency deadlocks.
- It is strictly between unique and shared.
Recommendation: It is suggested to use unique_ptr or shared_ptr instead of normal pointers to avoid memory leaks. It acts like Garbage Collection.
In-Class Initializer & Delegation of Constructors
In-Class Initializer
- In C++11, direct initialization of variables inside the class definition is allowed.
Delegation of Constructors
- We can allow a non-parameterized constructor to call a parameterized constructor.
- One constructor can call another constructor within the same class.
Ellipses (Variable Argument Lists)
- Requires:
#include <stdarg.h>or#include <cstdarg> - Ellipses are used for taking a variable number of arguments in a function.
- Example: A function to find the sum of integers, where we can pass 2, 3, 5, etc., elements.
- We must tell the function how many arguments we are passing (usually the first argument).
Syntax:
Calling:
- Mechanism: We use
va_list,va_start,va_arg, andva_endfunctions to work with ellipses. - This was a feature of C language (used in
printfandscanf), now available in C++. - Note: C++ also has function overloading and variadic templates which help with different numbers of arguments.