慢慢完善
一、右值引用 移动赋值
移动不分配新内存,接管被移动对象的内存后,源对象的指针置为nullptr,然后销毁,这样本来的内存会被留下来。
形式:
&a 左值引用, &&a右值引用
左值持久,右值短暂
int &&a =42 ; 对的,42字面常量是右值
int &&b = a; 错了, a变量时左值
int &&b = a*2; 错
新函数
int &&b = std::move(a); 显示调用移动构造。move()返回一个右值引用
要点:
1.移动操作不抛出异常
2.移动赋值运算符=
3.移动后源对象必须可析构
4.合成的移动操作和合成拷贝操作的条件大不相同。 大概是:如果一个类定义了自己的拷贝构造,拷贝赋值运算符,或析构函数,编译器就不会合成移动构造函数。 只有当一个类没有定义任何的版本控制成员,且数据可移动是,才会合成移动构造函数。
5.如果既有移动构造又有拷贝构造,则使用普通函数匹配规则确定使用哪一种。
用右值引用函数来受益:
void push_back(const X&); //拷贝:绑定到任意类型的X
void push_back(X &&); //移动:只能绑定到类型X的可修改的右值
定义移动构造函数
StrVec::StrVec(StrVec &&s) noexcept //不抛异常
:elements(s.elements),first_free(s.first_free),cap(s.cap)//接管资源(这里为指针)
{
s.elements = s.first_free = s.cap = nullptr; //准备析构
}
二、RAII(不一定是新特性,先放这儿)
在析构函数中写入对资源的释放,在该对象超出作用域时,自动调用析构函数时,自动对资源释放。
为什么会提出这个概念? 这不是早就有的特性吗?
三、constexpr常量表达式
四、lamdba
五、智能指针
六、function类模板
可调用对象可以为:函数,lamdba
在重载运算符的运用中,需要建立一个符号与可调用对象的关系。如:
Map<string,int(*)(int,int)> binops;
//将add函数指针加入map中
binops.insert({"+",add})
但Lamdba不是函数指针,无法加入到这个映射关系,所以可以用function类模板解决这个问题。
定义:map<string,function<int(int,init)>> binops。
再将lamdb赋值给一个function类型中,即可。
另:同时也解决了重载函数的问题,因为以前映射的时候连函数指针都没用,只传入了函数名,具体见c++primer。