C++11的右值引用和移动语义是如何工作的?
右值引用(&&)运行我们绑定到临时对象(右值),,这是C++11之前不允许的 。移动语义则允许我们将资源从一个对象移动到另一个对象,而不是复制他们。
范围-based for 循环 (Range-based for loop)
用于遍历容器中的元素,提供了一种更简洁。安全的遍历方式,避免了迭代器或下标可能引入的错误,使代码更加易于编写和理解。
auto
注意事项:
1、在运行时推导 2、必须进行初始化,只用推导一个类型 3、无法推出const属性 4、推不出引用
decltype
1、不需要初始化 2、能推出引用 3、在编译期推理,不会执行表达式逻辑 4、赋值表达式推出的是引用
template<typename T, typename U>
auto add(T a, U b)->decltype(a + b) //在编译器会推导 a + b
{
return a + b;
}
(auto 与 decltype 比较)
左值与右值比较
右值引用: 对右值进行引用 :&&
左值引用: 对左值进行引用 :&
左值:有内存有名字
右值:不能取地址没有名字,将亡值
移动语义: 对内存对象,不是拷贝,而是夺取
std::move() : 将左值变为右值,实现了资源的高效转移,避免了不必要的拷贝操作,提高了程序的性能
T&& :万能引用(必须要与模版在意一起) : 既可以接左值,又可以接右值
万能引用变量在被调用时右值也会被当成左值
std::forward<T> : 完美转发 :保持原变量的左右值特性
列表初始化 : {}
仿函数 : 用对象模拟函数
lambda
本质为仿函数,通过捕获列表扑获外部作用域一定范围的变量
表达式: 匿名函数 : [](){} 简化了对象的创建和使用
[] : 捕获列标
() : 参数列表
{} : 函数主体
[] : 不捕获任何变量,但不包括静态局部变量,lambda表达式可以直接使用
[&] : 按引用捕获外部作用域中所有变量,并作为引用在函数体里使用
[=] : 按值捕获外部作用域中所有变量,并作为副本在函数体里使用,但不能修改外部作用域变量的值
[this] : 一般用于类中,捕获当前类中的this指针,与成员函数具有一样的权限,访问成员变量
[变量名] : 捕获列表列出的变量,多个变量用 ,分隔
[= , &变量名] : 按值捕获外部变量,按引用捕获指定变量
[&, 变量名] : 按引用捕获外部变量,按值捕获指定变量
可调用函数 : 把仿函数,lambda,函数指针 三者进行整理封装,在头文件 #include <functional>
注意事项 : 不能发生 “引用悬挂” , 即按引用捕获会导致包含指向局部变量的引用,当lambda离开局部作用域时,会导致引用的哪个变量被释放,lambda里那个引用发生悬挂
模版
template<typename F, typename ...Args> //可变参数模版
void AddTask(F f, Args ...args)
{
auto fun = [f, args...](){f(args...);};
fun();
}
智能指针
基于范围的循环
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
for(auto& value : v)
{
value++;
std::cout<<value<<std::endl;
}
委托构造 继承构造
class A
{
public:
A(int a):a(a){}
A(int a, int b):A(a) //委托构造 : 委托已有的的构造函数帮助构造
{
this->b = b;
}
A(int a, int b, int c):A(a, b)
{
this->c = c;
}
private:
int a;
int b;
int c;
};
class B : public A
{
public:
using A::A; //继承构造 : 将父类的构造函数全部继承
};
nullptr : 代表空指针,有更强的安全性,可以避免一些类型转换错误
final : 最终类,不可被继承
default : 系统默认生成缺省函数
delete : 删除某个函数
verride : 用来防止虚函数写错虚函数名
explicit : 防止隐式转换
constexpr : 会在编译时计算表达式
enum
会判断类的变量是否可以相等(比如白色不会等于瘦)
enum class color
{
white,
black
};
enum class thickness
{
fat,
thin
};
int main()
{
if (color::white == thickness::thin)
{
std::cout<<"相等"<<std::endl;
}
else
{
std::cout<<"不相等"<<std::endl;
}
return 0;
}
字面量
: R"( )" : 会将括号里的字符都当普通字符解析
std::string path = R"(C:\User\)";
std::cout<<path<<std::endl;
forward_list : 前向列表
函数绑定器
std::placeholders::_1
auto f = std::bind(Chat, std::placeholders::_2, std::placeholders::_1);
//函数绑定器 : 可以修改函数的绑定形式 //std::placeholders::_1 : 表示原函数的第一个参数
f(20, 10);
注册机
std::map<std::string, std::function<void()>> callbacks;
callbacks["Login"] = Login;
callbacks["SignUp"] = [](){std::cout<<"注册"<<std::endl;};
int adminPwd = 100;
callbacks["adminSignUp"] = [adminPwd](){std::cout<<"管理员秘钥:"<<adminPwd<<std::endl;};