auto: Used for
type inference
//For variables
auto i = 42; // i is an int
auto l = 42LL; // l is an long long
auto p = new foo(); // p is a foo*
//For iterators
std::map<std::string, std::vector<int>> map;
for(
auto it = begin(map); it != end(map); ++it) {}
//For function return types
template <typename T1, typename T2>
auto compose(T1 t1, T2 t2)
-> decltype(t1 + t2)
{
return t1+t2;
}
auto v = compose(2, 3.14); // v's type is double
nullptr:
void display(int a){ cout<<"Integer version called"<<endl; }
void display(int *p){ cout<<"Int pointer version called"<<endl; }
void display(long a){ cout<<"long version called"<<endl; }
int main()
{
display(
nullptr);
//Calls pointer version
display(NULL);
//Calls long version
display(0);
//Calls int version
}
range-based for loop:
string str = "United Online";
for(char c : str)
cout<<c;
override:
- For runtime polymorphism,
1. Signatures of functions must be same in both Base and Derived classes.
2. Base class pointer is used to achieve this.
base * pb = new Derived();
- But there is a chance that by mistake the function signature is different in both Base and Derived classes. Unnoticeably, we might be thinking that runtime polymorphism will work and Derived version will be called. But ideally just compile time polymorphism will happen and Base version will be called.
- To avoid such bugs, 'override' is introduced. It will error out if function signatures are different.
class parent {
public:
virtual void handle_event(int something) {cout<<"Boring default code"<<endl;}
};
class child : public parent {
public:
// force handle_event to override a existing function in parent
// error out if the function with the correct signature does not exist
virtual void handle_event(int something)
override {cout<<"New exciting code"<<endl;}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
final:
- To stop Derived class overriding Base class virtual function.
- To stop inheriting Base class it self.
enums:
//Old style (Global scope)
enum Animals{Cat, Dog, Chicken};
enum Birds{Eagle, Duck, Chicken};
//Error, Chicken is already used
//New style (Seperate scope)
enum class Fruits{Apple, Mango, Orange};
enum class Colors : char{Red, Green, Orange};
//Allowed, Fruits::Orange != Colors::Orange
smart pointers: used for
reference counting and auto releasing of owned memory.
- unique_ptr: should be used when ownership of a memory resource does not have to be shared (it doesn't have a copy constructor), but it can be transferred to another unique_ptr (move constructor exists).
- shared_ptr: should be used when ownership of a memory resource should be shared (hence the name).
- weak_ptr: holds a reference to an object managed by a shared_ptr, but does not contribute to the reference count; it is used to break dependency cycles (think of a tree where the parent holds an owning reference (
shared_ptr
) to its children, but the children also must hold a reference to the parent; if this second reference was also an owning one, a cycle would be created and no object would ever be released).
On the other hand the auto_ptr is obsolete and should no longer be used.
lambdas: Nothing but a
nonymous functions
Eg: [](int n){cout<<n<<" ";}