Scott Meyers C++ Modern Effective2
Scott Meyers C++ Modern Effective2
During compilation, compilers use expr to deduce two types: one for T and one for
ParamType.
Steps : ignore ref => match "expr" with "paramType" to get "T"
That s true, but it doesn t matter. There s a direct mapping between template type
deduction and auto type deduction. There is literally an algorithmic transformation
from one to the other.
WHAT IS THE USAGE OF "decltype(auto)" It deduced to exact type of a expression , its useful in generic code
Auto -> like template type deduction decltype(auto) -> like expression is
============================================================================================================
In C++11, perhaps the primary use for decltype is declaring function templates
where the function s return type depends on its parameter types. For example, suppose
we d like to write a function that takes a container that supports indexing via
square brackets (i.e., the use of [] ) plus an index, then authenticates the user before
returning the result of the indexing operation. The return type of the function should
be the same as the type returned by the indexing operation.
operator[] on a container of objects of type T typically returns a T&. This is the case
for std::deque, for example, and it s almost always the case for std::vector. For
std::vector<bool>, however, operator[] does not return a bool&. Instead, it
returns a brand new object. The whys and hows of this situation are explored in
El 5olasa --> el [] fe el vector 3latol byrg3 ref msh el kema nfsha fa Lw T byrg3 T& laken el bool msh byrg3 &bool fa 3lshan kda m7tagen el
Decltype(auto) 3lshan mnsh5lsh dm8na be hyrg3 eh
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Braced initialzation ( uniform initialization) EL 5OLASA ENHA CONSTANT TNF3 FE KOL EL CASES
From <https://chat.openai.com/c/a5b3675f-9376-45ef-96d1-5bf553cd543b>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DrawBacks !!
Practically speaking, the same is true of NULL. There is some uncertainty in the details
in NULL s case, because implementations are allowed to give NULL an integral type
other than int (e.g., long)
The uncertainty regarding the behavior of f(NULL) is a reflection of the leeway granted
to implementations regarding the type of NULL. If NULL is defined to be, say, 0L
(i.e., 0 as a long), the call is ambiguous, because conversion from long to int, long
to bool, and 0L to void* are considered equally good
EL 5OLASA EL KLAM DA BY7SL FEL TEMPLATES BS 3LSHAN BY7SL TYPE DUDECTION FA EL TEMPLATE BY7WLA LE INT AW LONG AW AY KAN
LAKEN FEL FUNCTION EL 3ADY YNF3 ABASY 0 AW NULL LE FUNCTION BTA5OD SMART POINTER
Laken el klam da msh s7 fel enum 3l 3ady el visibilty byba2 local ll mkan el m3mol feh el enum
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Feh 3eb tany fel enum el 3adya hwa ano byt7wl l integrals type
The C++98 approach to preventing use of these functions is to declare them private and not define them
The difference between deleting these functions and declaring them private may
seem more a matter of fashion than anything else, but there s greater substance here
than you might think. Deleted functions may not be used in any way, so even code
that s in member and friend functions will fail to compile if it tries to copy
basic_ios objects.
============================================================================
An important advantage of deleted functions is that any function may be deleted,
while only member functions may be private.
Noexcept internally
Before noexcept (we called copycotr at every expand in capacity) After noexcept
constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile
time rather than run time
The justification is that declaring a copy operation (con struction or assignment) indicates that the normal approach to copying an
object(memberwise copy) isn t appropriate for the class, and compilers figure that if memberwise copy isn t appropriate for the
copy operations, memberwise move probably isn t appropriate for the move operations.
This goes in the other direction, too. Declaring a move operation (construction or
assignment) in a class causes compilers to disable the copy operations
So move operations are generated for classes (when needed) only if these three things
are true:
No copy operations are declared in the class.
No move operations are declared in the class.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
std::unique_ptr embodies exclusive ownership semantics. A non-null std::unique_ptr always owns what it points to.
Moving a std::unique_ptr transfersownership from the source pointer to the destination pointer. (The source pointer is set to null.) Copying a
std::unique_ptr isn t allowed, move-only type
By default, resource destruction is accomplished by applying delete to the raw pointer inside the std::unique_ptr.
All custom deletion functions accept a raw pointer to the object to be destroyed
A std::shared_ptr can tell whether it s the last one pointing to a resource by consulting the resource s reference count, a value associated with the resource that keeps
track of how many std::shared_ptrs point to it
std::shared_ptr constructors increment this count ,std::shared_ptr destructors decrement it, and copy assignment operators do both
The cyclic dependency problem with std::shared_ptr occurs when two or more objects hold std::shared_ptr to each other, creati ng a cycle of
ownership. This leads to a situation where the reference counts of these objects never reach zero, preventing them from being destructed
properly. As a result, memory leaks occur despite using std::shared_ptr.
Here's a simple example illustrating the cyclic dependency problem:
One solution to the cyclic dependency problem with std::shared_ptr is to break the cyclic dependency by using std::weak_ptr.
Here's how you can modify the previous example to use std::weak_ptr:
make_unique just perfect-forwards its parameters to the constructor of the object being created, constructs a std::unique_ptr from the raw pointer new
produces, and returns the std::unique_ptr so created
std::make_unique and std::make_shared are two of the three make functions:functions that take an arbitrary set of arguments, perfect-forward them to the
constructor for a dynamically allocated object, and return a smart pointer to that object.
I ve highlighted the essential difference: the versions using new repeat the type being
created, but the make functions don t. Repeating types runs afoul of a key tenet of
software engineering: code duplication should be avoided. Duplication in source
code increases compilation times, can lead to bloated object code, and generally renders
a code base more difficult to work with. It often evolves into inconsistent code,
and inconsistency in a code base often leads to bugs. Besides, typing something twice
takes more effort than typing it once
Rvalue references are the glue that ties these two rather disparate features together.
They re the underlying language mechanism that makes both move semantics and
perfect forwarding possible
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
std::move doesn t move anything. std::forward doesn t forward anything
1. The function is a template function with a single parameter param of type T&&, which is a universal reference. Universal references are declared using T&& and
can bind to both lvalues and rvalues.
2. Inside the function, remove_reference<T>::type removes any reference from T, ensuring that we get the underlying type without any reference qualifiers.
3. typename remove_reference<T>::type&& then adds an rvalue reference to the type obtained after removing the reference from T. This ensures that the function
returns an rvalue reference, regardless of the type of param.
4. Finally, static_cast is used to cast param to the appropriate reference type, based on the deduction of T. This ensures that the function returns an rvalue
std::forward is a conditional cast: it casts to an rvalue only if its argument was initialized with an rvalue.
You may wonder how std::forward can know whether its argument was initialized
with an rvalue. In the code above, for example, how can std::forward tell whether
param was initialized with an lvalue or an rvalue? The brief answer is that that information
is encoded in logAndProcess s template parameter T. That parameter is
passed to std::forward
Without RVO
With RVO
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++