放在成员函数末尾,只读,增强文章可读性
常量修饰符
限制方法修改数据
定义变量时是否需要初始化
int a=8;
const int *p=&a;
int *const p=&a
左定值,右定址,const 修饰不变量
编译关键字,用于简单函数,由编译器决定是否将具体函数替换使用
使用后拒绝隐式转换,防止单参构造函数的隐式转换
delete调用
非成员函数但能使用成员变量
只能重载c++中存在的运算符
左侧为成员对象
强转:由大到小, 语法:函数型和类c型
隐式转换: 由小到大,不需要用户干预,编译器私下进行的类型转换,explicit拒绝隐式转换
默认构造函数
默认析构函数
复制构造函数
应该的原型:
Class_name(const Class_name &);
然而默认复制函数,确是值复制,即浅复制
赋值构造函数
与复制构造函数相同:
Class_name& Class_name::operator=(const Class_name &);
地址构造函数
前者: 用对象初始化对象,对象以值传递的方式传递给函数,函数局部对象以值传递的方式从函数返回
后者:对象赋值给对象
1,关键字:virtual
2,如果使用指向对象的引用或指针来调用虚方法,程序将使用对象类型定义方法,而不使用为引用和指针类型定义的方法,
二义性问题,分为:
1.作用域限定符 基类::
2.子类重写父类方法
1.作用域限定符 基类::
2.子类重写父类方法
3.虚基类,虚继承
3,如果定义的类将被用作基类,则应将那些要在派生类中重新定义的类方法声明为虚方法
防止内存泄漏,->拓展:
什么是内存泄漏,内存溢出
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
[C++]虚析构函数的作用 - zhizhiyu - 博客园 (cnblogs.com)
虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的。
new一个自定义对象时,会调用对象的构造函数,delete则会调用析构函数
int *a = new int(10); //动态创建整型数,无参数是 * a=0,有参数则 * a = 参数
int *p = new int[10]; //创建一个有10个元素的动态整型数组,没有赋值,元素为随机数
int *p = new int[10] (); //创建一个有10个元素的动态整型数组,并都赋值为0
面试题
malloc/free与new/delete的区别:
1.操作符与函数
2.空间是否能初始化
3.malloc的返回值必须强制类型转换,因为是(void*)型
4.申请自定义对象内存空间时,malloc/free只能开空间,而后者能调用对应函数操作
5.malloc申请失败返回NULL,new抛出异常
6.malloc申请需要手动计算空间大小
int *pt=new int;
pt 指针
*pt等同于一个int类型的变量
[外部变量访问方式说明符](参数)mutable noexcept/throw()->返回值类型{函数体;}
[=]: 以值传递的方式,导入所有外部变变量,只能读
[&]: 以引用传递的方式,导入所有外部变量,能读能写
auto使用时必须对变量初始化
禁用:
auto 不能用在函数参数中
auto 不能用于类的非静态成员变量
auto 关键字不能定义数组
auto 不能用于模板
自动类型推导,返回表达式类型,语法:decltype(expression)
vector{1,2,3,5};
std::unordered_mapm={
{1,"one"},
{2,"two"},
{3,"three"}
}
int a=10;
a是左值,
10是右值
int &&r1=13;
&&实现右值引用声明
右值分类:
左值到右值 std::move()
右值不能转化为左值,但右值能通过赋值给右值引用提高生命周期
Matrix(Matrix &&Matr) { // 五法则移动构造:当内存管理对象使用右值构造,保证内存管理资源不被冗余使用
size_ = Matr.size_;
data = Matr.data;
Matr.data = nullptr;
}
using 新类型=就类型
final 与override都是放在被修饰函数后,
final(最终)修饰函数,子类不能重写,final修饰类,不能不能被继承
子类重写父类的方法的声明中,将override放在函数后,必须重写
类似于指针的类对象
auto_ptr
unique_ptr
//上面两个同属于所有权模型
shared_ptr
//要想使用以上对象需使用#include
share_ptr采用引用计数的方法,当引用计数为0时调用析构函数
1.unique_ptr 类中把拷贝构造函数,与拷贝赋值声明为private或delete,这样就不可以对指针指向进行拷贝,也就不能产生指向同一个对象的指针
定义:。。。
实现: lambda表达式
仿函数
std::bind (用于给一个可调用对象赋值,生成新的可调用对象)
std::function包装器 (可用function
引用是已定义的变量的别名
&a =>可解释为对变量a起别名
++ dynamic_cast
是否可以安全地将对象的地址赋给特定类型的指针,true,返回对象指针,否则,返回空指针
const_cast
(可能有点理解错误)应该是把const 修饰变量暂时变成可修饰的,妈的太复杂,别用了吧
++ static_cast
使用static_cast可以明确告诉编译器,这种损失精度的转换是在知情的情况下进行的,也可以让阅读程序的其他程序员明确你转换的目的而不是由于疏忽。
reinterpret_cast
友元类能直接使用基类的私有部分
作用于通用编程,有类模板,函数模板,复杂的要死
类模板的声明与定义只能写在一个.h头文件
当你想告知编译器iterator是类型而不是变量,只需要用typename:
解释多态的含义
多态分为静态多态和动态多态,
1.静态多态的实现:函数重载,运算符重载,泛型编程
2.动态多态:在程序运行时根据基类的引用指向的对象来确定自己具体该调用哪一个类的虚函数,
表现效果:同样的调用语句在实际运行时有多种不同的表现效果
调试的目标文件是可执行文件(.c文件编译后的文件)
编译时需要用gcc -g testgdb.c -o testgdb.exe
gcc -g testgdb.cpp -o testgdb.exe调加编译信息
1.启动
gdb 文件
2.打断点
b 行号
查看断点信息
info br
3.运行程序
run [args]
3.调试
n (next) 把函数当成指令 回车同理
s (step) 进入函数
c 执行到下一个断点或结束
4.查看
print
print &d //地址
char buf[20]="hello world";
print buf //输出字符串
x/s buf //输出字符串
int data[3]={2,3,4};
print data //输出数组所有数据
5.退出
quit
只能声明,没有实现
Person p1;
Person p1=Person();
方法调用:
p1.functionName();
Person *p1=new Person();
p1->functionName();
如果有多个调用者(callers)同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者
自我理解:如果有AB两个对象完全相同,我完全可以在内存中只创建一份对象,将两个指针指向同一内存资源,需要修改时,再去复制一份专用的副本,给修改的调用者
string类在c++11前运用过此项技术,c++11后为多线程放弃了
默认的访问权限,
ps:struct自定义类型,编译器自动为其生成默认构造函数
父类的纯虚函数必须重写,
父类的虚函数可以选择性重写