auto 关键字:
用于定义变量,编译器可以自动判断变量的类型。
auto i = 100;
auto p = new A();
auto k = 34343LL;
map<string,int,greater<string>> mp;
for (auto i = mp.begin();i!= mp.end();++i) {
cout<< i->first<<"."<<i->second;
}
auto 关键字可以解决模板返回值的类型不能是我们定义的类型之外的值,编译器自动判断返回值的类型。
#include<iostream>
using namespace std;
class A
{
};
A operator+ (int n,const A& a) {
return a;
}
template <class T1,class T2>
auto add(T1 x,T2 y) ->decltype(x+y) {
return (x+y);
}
int main() {
auto d = add(100,1.5);
auto c = add(100,A());
cout<<d;
decltype(c);
return 0;
}
基于范围的for循环
#include<vector>
#include<map>
#include<iostream>
using namespace std;
void print(int ary[],int size) {
for(int i= 0;i< size;i++)
cout<<ary[i]<<" ";
}
int main() {
int ary[] = {1,2,3,4,5};
for(int &e :ary) {
e *= 10;
}
for(int e: ary)
cout<<e<<" ";
cout<<endl;
vector<int> st(ary,ary+5);
for(auto & it: st)
it *= 10;
for(int it:st)
cout<<it<<" ";
}
for(int &e:ary) :意思是e是ary里面的每一个元素的引用。
for(int e : ary):意思是变量ary里面的每一个元素。
vetor这种类型,可以用auto定义变量,让编译器自动判断类型,不用我们自己判断类型。
for(auto & i :st);
右值引用和move语义
右值:一般;来说,不能取地址的表达式,就是右值,能取地址的,就是左值。
class A{}
A & r = A();//error,A()是无名变量,是右值
A&& r = A();//ok,r是右值引用
主要目的是提高程序执行的效率,提高不必要的需要进行深拷贝的对象进行深拷贝。
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
class String{
public:
char* str;
String():str(new char[1]) {str[0] = 0;}
String(const char*s) {
str = new char[strlen(s)+1];
strcpy(str,s);
}
String(const String& s) {
cout<<"copy constructor called"<<endl;
str = new char[strlen(s.str)+1];
strcpy(str,s.str);
}
String& operator= (const String & s) {
cout<<"copy operator = called"<<endl;
if(str!= s.str) {
delete[] str;
str = new char[strlen(s.str)+1];
strcpy(str,s.str);
}
return *this;
}
//move constructor
//不进行深拷贝,直接把s的内存搬过来
String(String && s):str(s.str) {
cout<<"move constructor called"<<endl;
s.str = new char[1];
s.str[0] = 0;
}
//move assigment
String& operator= (String &&s) {
cout<< "move operator = called"<<endl;
if(str!=s.str) {
delete[] str;
str = s.str;
s.str = new char[1];
s.str[0] = 0;
}
return *this;
}
~String() {delete[] str;}
};
//调用了move constructor时,右值的变量的内容会被改写,所以,仅适用于a = b,赋值后b就没用了。
// a = B();临时变量在赋值号的右边,B()是临时变量,肯定不会有用的。
//一般情况下,需要进行三次的深拷贝,但此处适用move语义一次深拷贝都不需要。
template<class T>
void MoveSwap(T& a,T& b) {
T tmp(move(a));//std::move(a)为右值,这里会调用move constructor
a = move(b); //move(b)为右值,这里调用move assignment
b = move(tmp); //move(tmp)为右值,这里调用move assignment
}
int main() {
String s;
s = String("ok");//右值,调用move assignment
cout<< "******"<<endl;
String && r = String("this");
cout<< r.str<<endl;
String s1 = "hello",s2 = "word";
MoveSwap(s1,s2);
}