c++左值、右值、完美转发、万能引用、参数展开
左值、右值
void processInt(int& i) {//代表传入的参数是左值std::cout << "Processing lvalue int: " << i << std::endl;
}
void processInt(int&& i) {//代表传入的参数是右值std::cout << "Processing rvalue int: " << i << std::endl;
}
实验:
int main()
{int i=0;processInt(0);//右值processInt(i);//左值return 0;
}
完美转发——将变量本身传递给函数(不论左值、右值)
万能引用——避免不必要的变量复制和构造
void processInt(int& i) {//代表传入的参数是左值std::cout << "Processing lvalue int: " << i << std::endl;
}
void processInt(int&& i) {//代表传入的参数是右值std::cout << "Processing rvalue int: " << i << std::endl;
}
template<typename T>
void Tran(T&& d)//万能引用,不管传入是左值还是右值,d都和传入的一致
{proceessInt(std::forward<T>(d));//完美转发,把d不变转发给函数,可以避免不必要的构造和复制。
}
实验:
int main()
{int i=0;Tran(i);//调用的是左值函数Tran(0);//调用的是右值函数return 0;
}
模板函数
//常见用法
template<typename T,typename K>
void f(T d1, K d2)
{std::cout<<d1<<d2;return;
}
f(1,'c');
f('c','c');//部分参数形式确定的模板
template<int N,typename K>
void f(K d1)
{std::cout<<N<<d1;return;
}
f<1,char>('6');
f<1,string>("123");
参数展开
template<typename T,typename... Args>//模板函数指定返回值,输入参数是参数包arg
T* test(Args&&... arg)
{T*t = reinterpret_cast<T*>(operator new(size_of(T)));//分配内存空间并且转换指针类型new(t) T(std::forward<Args>(arg)...);//将参数包展开,完美转发
}
举例
myclass* t = test(1,2,3,'c');
//模板函数对应为
myclass* test(int&&t1,int&&t2,int&&t3,char&&t4)
{
myclass* t = reinterpret_cast<myclass>(operator new(size_of(myclass)));
new(t) myclass(std::forward<int>(t1),std::forward<int>(t2),std::forward<int>(t3),std::forward<char>(t4));//将参数包展开,完美转发
}
T* test(Args&&... arg)
{T*t = reinterpret_cast<T*>(operator new(size_of(T)));//分配内存空间并且转换指针类型new(t) T(std::forward<Args>(arg)...);//将参数包展开,完美转发
}