Frequently used C++11 Features
auto
In C++98,
you must specify the type of an object when you declare it. C++11 takes
advantage of this, letting you declare objects without specifying their types. auto is now a sort of placeholder for a type, telling the
compiler it has to deduce the actual type of a variable that is being declare.
auto i = 30; // i is an int
auto l = 90LL // l is an lon long
auto c = ‘a’ ; // char
vector<int> vi;
vector<int>::iterator ci = vi.begin();
instead we ca declare the iterator like this.
auto ci = vi.begin();
nullptr – At
last, C++ has a keyword that designates a null pointer constant. nullptr replaces the bug prone NULL
macro and the literal 0 that have been used as null pointer substitutes for
many years.
Void f(int); // Line
1
Void f(char *); // Line 2
// C++ 98
f(0) ; // Which f is called ? Ambiguous
// C++11
f(nullptr) ; // UnAmbiguous. Calls Line 2
Range based for loops
C++11 extends the syntax of the for statement to allow for
easy iteration over a range of elements. This form will iterate over each
element in the list. It works for C-style arrays, initializer lists, and any
type that has begin() and end() functions defined for it that return iterators.
For example –
Std::map<std::string, std::vector<int>> map;
Std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
map[“ONE”] = v;
for(auto& mapIter : map)
{
Cout<<mapIter.first;
for(auto
vecIter : mapIter.second)
{
Cout<<vectorIter;
}
}
Override and final
Virtual methods was badly designed in C++98, because there
was’nt a mandatory mechanism to mark virtual methods as overridden in derived
classes. It is possible to accidentally create a new virtual function, when one
intended to override a base class function. For example :
Class Base
{
Public:
Virtual
void func() const
{
Cout<<”This
is constant BASE :”;
}
};
Class derived : public base
{
Public:
Virtual
void func()
{
Cout<<”This
is a Non Constant DERIVED : ”;
}
};
Int main()
{
Base *d =
new Derived();
d->func();
delete d;
return 0;
}
Output :
This is constant BASE
If const is
removed in the base version of func, it prints “This is a Non Constant DERIVED”
.
Virtual void func() is actually of a different signature
than virtual void func() const. Thus we did’nt override the original, read-only
base function. We ended up creating a new virtual function instead of Derived.
If we would have used the keyword “override” in the derived
func, then the compiler gives an error message
Error: 'virtual void Derived::func()' marked override, but
does not override
The override special identifier means that the compiler will
check the base class to see if there is a virtual function with this exact
signature.
Final :
C++ also adds the ability to prevent inheriting from classes
or simply preventing overriding methods in derived classes. This is done with
the special identifier “final”.
Class A final
{
Virual void
f(int);
}
Class B
{
// No class
can override f()
Virtual
void f() final ;
}
Default and delete specifiers.
Default : A function in the form (=default) is called a
defaulted function. The =default ; part instructs the compiler to generate the
default implementation for the function. Defaulted functions have two
advantages :
a.
They are more efficient than manual
implementations
b.
They rid the programmer from the chore of
defining those functions manually.
Class Base
{
Base() =
default; // C++11
Virtual ~Base()
= default; // C++11
};
The opposite of defaulted functions is a deleted function:
Int func() = delete;
Deleted functions are useful for preventing object copying,
among the rest. Recall that C++ automatically declares a copy constructor and
an assignment operator for classes. To disable copying, declare these two special
member functions = delete;
Class NonCopyable
{
NonCopyable
(const NonCopyable& ) = delete;
NonCopyable&
operator=(const NonCopyable &) = delete;
}
NonCopyable a;
NonCopyable b (a) ; // Compilation
Error, Copy constructor is deleted.
Lambdas functions
C++11 provides the ability to create anonymous functions,
called lambda functions. It allows a function to be defined at the point where
it’s needed in another expression. It is a function that we can write inline in
our code to pass in to another function. We can use lambdas wherever a function
object or a functor is expected.
A lambda expression has the form :
[capture] (parameters)->return-type{body}
The [] construct inside a function call’s argument list
indicates the beginning of a lambda expression.
Suppose we want to count how many uppercase letters a string
contains. Using for_each() to traverse
a char array, the following lambda expression determines whether each letter is
in uppercase. For every uppercase letter it finds, the lambda expression increments
Uppercase, a variable defined
outside the lambda expression.’
Int main()
{
char s[]=”Hello
World”;
int Uppercase
= 0; // Variable which will be modified by the lambda.
for_each(s,s+sizeof(s),[&Uppercase](char
c) {
if(isupper(c))
Uppercase++;
});
cout<<”UpperCase
Letters : ”<<Uppercase<<endl;
}
It’s as if you have defined a function whose body is placed
inside another function call. The ampersand in [&Uppercase] means that the
lambda body gets a reference to Uppercase so it can modify it. Without the
ampersand, Uppercase would be passed by value.
Sample lambda function to print the container.
Int main()
{
Vector<int>
v = {1,2,3,4,5};
For_each(v.begin(),v.end(),[](int
n) {cout<<n<<endl;});
}
More examples :
Int main()
{
// 1’st
Lambda function
cout<<
[] (int a, int b) { return a*b; } (4,5) <<endl;
// 2nd
Lambda Function
auto f = []
(int a, int b) {return a*b ; };
cout<<f(4,5);
//
Explicitly specify the return type of a lambda function.
cout <<[]
(int a)->int { return n*n; } (5) ;
}
Output:
g++ -std=c++11
lambda.cpp
20
20
Comments
Post a Comment