1 新的初始化方式
可以用{}进行初始化
using std::string;
int a=10;//old
int b(20);//old
int c{10};//new
char c={'s'};//new
struct MyStruc
{
char c;
short a;
string s;
};
MyStruc inst{'s',88,"wanna"};
也可以用于自定义类型初始化。类的初始化有四种方式:{},默认构造,有参构造,拷贝构造。第一种尽量不用
2 nullptr关键词与NULL
nullptr表示空指针,是一个关键词
NULL是老版本的,是一个0的宏
3 取别名typedef 和using
注意:函数指针名就是变量名
int fun(int a,int b)
{
return a*b;
}
using pFun=int(*)(int ,int);//新版给函数指针类型取别名
//typedef int(*pFun)(int,int);//老版
pFun p=fun;
p(3,4);
4 decltype()获取变量类型关键词
decltype()//获取变量类型
decltype(())//获取指定变量的引用类型
int a{926};
decltype(a) num=10;//获取了a的类型为int,并定义int变量num
decltype((a)) numR=a;//定义a变量的引用
numR=90;//
cout<<a<<endl;//此时的a通过引用numR改变值为90
5 auto自动类型关键词
auto定义变量需要给定初始值,编译器通过初始值推导变量类型。
使用一个auto定义多个变量时,所有的推导类型必须一致。
auto在函数中可以给函数返回值类型后置确认(用的不多,感觉鸡肋…)。
auto a=10;//int类型
auto s="abcde";//const char*
auto fun()->string//指定函数类型为string
{
}
6 新的for规则
用于有迭代器iterator的模板
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name="Asir";
for(char i:name)
{
cout<<i<<' ';
}
return 0;
}
7 类成员变量设定缺省参数
**注意:**头文件里面不能含有有内存的东西,否则,变量重定义
class CA
{
int a=10;//知识给定缺省参数,不会申请内存,如果在实例化时给定值,则覆盖,否则把10给a
};
8 default 在类中的作用
可以定义默认构造
//下面🌰成立
class CA
{
public:
int a=10;
CA()=default;
};
//main()
CA a;
cout<<a.a<<endl;
9 委托构造
当一个类有多个构造时,一个构造可以调用其他的构造。委托构造是在初始化成员列表实现
class CA
{
public:
CA() = default;
CA(string n)
{
cout << "有参string" << endl;
}
CA(int a) :CA("zhend")
{
cout << "有参int" << endl;
}
~CA()
{
cout << "析构" << endl;
}
};
int main()
{
CA a(12);//此处执行结果为:第一行:有参string第二行:有参int第三行:析构
return 0;
}
10 final关键词
1.final关键字修饰类,表示这个类不能被继承。格式为在类名后面添加final
2.修饰类中虚函数成员,表示这个虚函数(必须是类中虚函数)必须被继承。格式为在函数参数列表后面添加final
//1
class CA final
{
};
class CB:public CA//error
{
};
//2
class CA
{
public:
virtual void fun()final
{
cout<<"CA_fun";
}
};
class CB:public CA
{
public:
virtual void fun()//error,the virtual function is final,in CA::fun
{
cout<<"CA_fun";
}
};
//2
override关键词
表示被修饰的函数必须重写基类中的虚函数
作用1:提示读者某个函数重写了基类虚函数
作用2.强制编译器检查某个函数是否重写基类虚函数
格式为:在函数参数列表后面添加override
class CA
{
public:
virtual void fun()
{
cout << "Afun" << endl;
}
};
class CB :public CA
{
public :
int a;
void fun() override//合法的
{
}
CB() {
cout << "CB构造" << endl;
}
};
智能指针
auto_ptr
auto_ptr是c98提出的,在c++11基本不再使用,由unique_ptr替代,原因是unique_ptr比auto_ptr更加灵活方便安全,使用auto_ptr因为可以进行两个指针赋值拷贝的操作,也就意味着在开发时可能出现一个内存的多个引用,导致逻辑混乱,对应一个快内存多次释放,导致程序因内存管理不当而崩溃
所以不建议使用
unique_ptr
**原理:**同一块内存所有控制权只由一个指针完全接管。
定义方式:
模板参数一是需要定义什么类型的指针,第二个参数(一般不写)指定用什么类型的delete释放
unique_ptr<int ,int> v(new int(9));
//动态数组分配
unique_ptr<int[]> g(new int[3]{ 1, 2, 3 });
cout << g[1] << endl;
常用函数:
**T *get();**返回这个智能指针的原始指针类型,如果为空,则返回unllptr
unique_ptr<int> p(new int(20));
int* p1= p.get();//合法,但这样就破坏了unique_ptr设计原理,
//同一块内存所有控制权只由一个指针完全接管。一般交换所有权使用reset
get()函数常用来判断是否为空,再做操作,更安全。
if(p.get()!=nullptr)
{
...
}
T release()*//释放所有权,释放并将内存空间返回,原指针被置为空
unique_ptr<int> p;
p.reset(new int(12));
p.release();
if(p.get()==nullptr)
{
//会进来
}
void reset(接受其他指针参数,或者缺省,缺省时置为nullptr);
重写分配内存,原来的内存会被释放。
unique_ptr<int> p;
p.reset(new int(12));
unique_ptr<int> p1(new int(90));
p.reset(p1.release());//release使p1指向了空
//p开始指向int(12)的内存被释放,指向int(90)的内存。
void move(pointer);
使用move移动控制所有权,原来的指针会被置空
unique_ptr<int> v(new int(9));
unique_ptr<int> t= move(v);//使用move移动控制所有权,原来的指针会被置空