c++新特性
auto
auto自动推导变量类型;auto 需要初始化,auto不能定义数组。
//void func(auto x);也是错误的!!!
auto n=10;
auto f=12.8;
auto p=&n;
vector<int>::iterator it;
auto p=it;
auto a=10,b=12;
//auto a=10,n=12.3;不要有二义性会报错!!
//auto x;没有给变量类型
实际应用的例子!迭代器的使用
#include <iostream>
#include<vector>
int main()
{
vector<int> v = {1,2,3,4,5};
// vector<int>::iterator it = v.begin();
auto it = v.begin();
}
decltype
short a=100;//两个字节
short b=100; //两个字节
decltype(a+b) c;//得到int 类型的c
int n=0;
decltype(n) x;
auto x = n;
const int &r =n;
// decltype(r) y; 会报错因为引用使用的时候必须初始化但是y没有 被初始化。
decltype(r) y=n;
decltype(Class Student::total)c=0;
decltype(stu.name) url = "hello";
函数的用法比较常见
decltype(func(10)) ret = func(100);
基于范围的for循环
如下所示:
for(declaration:expression)
{
//循环体
}
其中declaration:定义一个变量,变量类型为要遍历序列中存储元素的类型。可以使用auto关键字
expression:表示要遍历的序列,常见的数组和容器
vector<int> v={1,2,3,4,5};
for(auto item:v)
{
cout<<item<<endl;
}
列表初始化
初始化const 成员属性。
class Foo
{
public:
int _x;
Foo(int x):_x(x) // 列表初始化 _x = x;
}
使用using 定义 别名
using db = double;
typedef void(*function)(int,int); //函数指针类型定义
using function = void(*)(int,int); // 函数指针类型
map<string,int> m1;
//重定义std::map
typedef std::map<string,int> map_int;
using map_int = std::map<std::string,int>;
final关键字
1.修饰一个类不能被继承
2.
class A final
{
public:
A(){};
}
override重写
override 直接写在虚函数的末尾,用于检查派生类的重写父类虚函数是否存在
右值引用
左值表示可以获取地址的表达式,他能出现赋值语句左边。
右值表示无法获取地址的对象,有常量值,函数返回值,lambda表达式。
通过右值给临时变量生存周期
右值的生命周期结束,临时对象会被销毁,析构函数被调用
int a;
int b=0;
a=10;//可以获取a的地址,因此为左值。
a = b // a b 都是左值,b的值(0 常量)可以当做左值使用!
右值引用可以修改
int num =10;
// int &&a = num; 右值引用不能初始化左值
int && a=10;
class AA
{
public:
int a = 33;
};
AA getintmum()
{
return AA();
}
int main()
{
/*ThreadPool tp(4);
for (int i = 0; i < 8; i++)
{
tp.enqueue([i] {
std::cout << "task:" <<i<< "is running..." <<std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "task:" << i << "is done..."<< std::endl;
});
}*/
int ii = 3;
auto f = [ii](const int& no) {
std::cout << "亲爱的" << no << "号,傻傻鸟" << std::endl;
};
AA&& aa = getintmum(); // 通过右值一直给临时变量生存周期
// aa 对象的生命周期结束,临时对象会被销毁,析构函数被调用
AA ip = getintmum();
std::cout << aa.a << std::endl;
std::cout << ip.a << std::endl;
return 0;
}
协程
协程的本质是暂停和恢复函数
c++中关键 co_await,co_yield,co_return 三个关键字的其一就是协程。
co_awaut 用于暂停协程直到恢复。
lambda函数使用方法
->void{};
一。参数列表,没有默认参数,所有参数必须有参数名,不支持可变参数。
[] 属于捕获列表 若lamda函数体使用外部参数,必须要把参数放入捕获列表中
通过捕获列表可以访问父作用域中的非静态局部变量,静态局部变量可以直接访问,不能访问全局变量。
捕获列表在书写[]中,与函数参数的传递类似,捕获方式可以是值和引用。
若要修改捕获列表中的值,需要采用引用。
[=] [&] 表示自动捕获变量
int ii = 3;
auto f = [ii](const int& no) {
std::cout << "亲爱的" << no << "号,傻傻鸟" << std::endl;
};
移动语义
move 函数将左值转换为右值
class AA
{
public:
int* m_data = nullptr; //数据成员,指向堆区资源的指针。
AA() = default;
void alloc()
{
m_data = new int;
memset(m_data, 0, sizeof(int));
}
AA(const AA& a) // 拷贝构造
{
std::cout << "调用构造函数" << std::endl;
if (m_data == nullptr) alloc();
memcpy(m_data, a.m_data, sizeof(int));
}
AA( AA&& a) // 移动构造
{
std::cout << "调用移动构造函数" << std::endl;
if (m_data != nullptr) delete m_data; // 如果已经分配内存,先释放掉。
m_data = a.m_data; // 把数据从元对象中拷贝过来
a.m_data = nullptr;
}
AA& operator=(const AA& a)
{
std::cout << "赋值构造" << std::endl;
if (this == &a) return *this; // 避免自我赋值
if (m_data == nullptr) alloc(); // 如果没有分配内存,就分配
memcpy(m_data,a.m_data,sizeof(int));
return *this;
}
AA& operator=( AA&& a) //移动赋值函数
{
std::cout << "赋值构造" << std::endl;
if (this == &a) return *this; // 避免自我赋值
if (m_data == nullptr) alloc(); // 如果没有分配内存,就分配
memcpy(m_data, a.m_data, sizeof(int));
return *this;
}
~AA()
{
if (m_data != nullptr)
{
delete m_data; m_data = nullptr;
}
}
};
int main()
{
auto f = [] {
AA aa;
aa.alloc();
*aa.m_data = 8;
return aa;
};
AA a4(f()); // 调用移动构造函数
AA a2 = std::move(a4);
return 0;
}
完美转发
- 如果模板中函数的参数名书写位T&& 参数名,
那么函数既可以接受左值引用,也可以右值引用。
2.提供模板书std::forward(参数),用于转发参数,
如果参数是右值,转发之后仍是右值引用;如果参数是一个左值,转发之后仍是左值引用。
void func1(int& i)
{
std::cout << "左值引用" << std::endl;
}
void func1(int&& i)
{
std::cout << "右值引用" << std::endl;
}
template<typename TT>
void func(TT&& ii)
{
func1(std::forward<TT>(ii));
}
int main()
{
int ii = 3;
func(ii);
func(8);
return 0;
}
可变参数模板
void print()
{
}
template <typename T,typename ...Args> // 三个点表示可变参数
void print(T arg, Args...args)
{
std::cout << "参数" << arg << std::endl; // 显示本次展开的参数
print(args...);//继续展开参数
}
智能指针
unqiue_ptr 独享他只用的对象,也就是说,同时只有一个unqiue_ptr指向同一个对象,当这个unqiue_ptr指向同一个对象,当这个unqiue_ptr被销毁时,指向的对象也随即被销毁。
包含头文件#include
class AA
{
public:
std::string m_name;
AA() { cout << "构造函数" << endl; };
AA(const string& name) { cout << "构造函数" << this->m_name << endl; };
~AA() { cout << "调用了析构函数" << endl; };
};
int main()
{
/*ThreadPool tp(4);
for (int i = 0; i < 8; i++)
{
tp.enqueue([i] {
std::cout << "task:" <<i<< "is running..." <<std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "task:" << i << "is done..."<< std::endl;
});
}*/
AA* p = new AA("西施");
unique_ptr<AA> pu1(p);
return 0;
}