UTILITY
swap
#ifndef V_H
#define V_H
class V
{
private:
int size;
int *array;
public:
//constructor
V()
{
std::cout<<"Default Constructor ..."<<std::endl;
size = 0;
array = 0;
}
V(int s):size(s)
{
array = new int[size];
for(int i = 0; i < size; i++)
array[i] = 10*i;
}
//copy constructor
V(const V &right):size(right.size), array(size?new int[size]:nullptr)
{
std::cout<<"Copy Constructor ..."<<std::endl;
std::copy(right.array, right.array+size, array);
std::cout<<"End Constructor ..."<<std::endl;
}
int *getAddress() const {return array;}
void display() const
{
for(int i = 0; i < size; i++)
std::cout<<array[i]<<" ";
std::cout<<std::endl;
}
//copy assignment
const V& operator=(const V &right)
{
std::cout<<"Copy Assignment ..."<<std::endl;
V temp(right);
std::swap(size, temp.size);
std::swap(array, temp.array);
std::cout<<"End Assignment ..."<<std::endl;
return *this;
}
~V()
{
std::cout<<"Destructor ..."<<std::endl;
delete [] array;
array = 0;
size = 0;
}
};
#endif
#include <iostream>
#include "V.h"
int main(int argc, char *argv[])
{
V v(10);
V v2(20);
std::cout<<"Swap ..."<<std::endl;
std::swap(v, v2);
std::cout<<"Ends Swap ..."<<std::endl;
v.display();
v2.display();
return 0;
}
- In swap, one copy constructor is called, two assignment constructors are called
//C++98
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
//C++11
template <class T> void swap ( T& a, T& b )
{
T c(std::move(a)); a=std::move(b); b=std::move(c);
}
- If no move constructor and move assignment, swap(*this, temp) of C++98 version will be called in assignment constructor and cause recursive calling of asssingment constructor
- If has move constructor and move assignment, swap(*this, temp) of C++11 will called
#include <iostream>
#include "V.h"
int main(int argc, char *argv[])
{
V v(20);
V v2(40);
v2 = v;
v.display();
return 0;
}
pair
#include <iostream>
#include <string>
#include <utility>
#include <typeinfo>
int main(int argc, char *argv[])
{
std::pair <std::string, int> planet;
//make_pair
planet = std::make_pair("Earth", 4);//C++11 style
//planet = std::pair<std::string, int>("Earth", 4);//C++98 style
//access pair
std::cout<<planet.first<<" "<<planet.second<<std::endl;
//get
std::get<0>(planet) = "Mars";
std::get<1>(planet) = 5;
std::cout<<std::get<0>(planet)<<" "<<std::get<1>(planet)<<std::endl;
//tuple_size
std::cout<<std::tuple_size<decltype(planet)>::value<<std::endl;
//tuple_element
std::cout<<typeid(std::tuple_element<0, decltype(planet)>::type).name()<<std::endl;
return 0;
}
make_pair
#include <iostream>
#include <string>
#include <utility>
int main(int argc, char *argv[])
{
std::pair <std::string, int> planet;
//make_pair
planet = std::make_pair("Earth", 4);//C++11 style
//access pair
std::cout<<planet.first<<" "<<planet.second<<std::endl;
return 0;
}
forward
#include <iostream>
#include <string>
#include <utility>
template <class T>
void display(T &p)
{
std::cout<<"Pass lvalue: "<<p<<std::endl;
}
template <class T>
void display(T &&p)
{
std::cout<<"Pass rvalue: "<<p<<std::endl;
}
int main(int argc, char *argv[])
{
std::string str = "Hello World!";
display(str);//lvalue
display("Hello World!");//lvalue
display(std::forward<std::string>("Hello World!"));//rvalue
display(std::move(str));//rvalue
return 0;
}
- If argument is rvalue reference, return rvalue reference
- If argument is lvalue reference, return lvalue reference
- Deduced parameters are evaluated as lvalue, even those parameters are rvalue, to solve it, use std::forward
move
#include <iostream>
#include <string>
#include <utility>
template <class T>
void display(T &p)
{
std::cout<<"Pass lvalue: "<<p<<std::endl;
}
template <class T>
void display(T &&p)
{
std::cout<<"Pass rvalue: "<<p<<std::endl;
}
int main(int argc, char *argv[])
{
std::string str = "Hello World!";
display(str);//lvalue
display(std::move(str));//rvalue
return 0;
}