1 | // 构造函数的对象属性初始化列表 |
C++ 申请和释放动态堆内存
1 | void funcc(){ |
NDK实现热修复的原理
C和C++中,内存分区:栈、堆、全局(静态、全局)、常量区(字符串)、程序代码区
同样,Java也分为五大区:
1,虚拟机栈(JVM Stack),存对象引用,基本数据类型
2,本地方法栈(Native Method Stack)
3,方法区(常量,静态变量以及编译后的代码)
4,程序计数器
5,直接内存
热修复原理:
每一个类对象中都保存有每个方法的地址指针,调用方法实际就是通过这些指针去方法区调用
对应的方法对象。热修复就是通过这种原理实现的。在不进行重启的情况下,将不同的方法加载
到内存中,然后,动态地将原来的对象方法指针重新指向该新的方法。
常量和常函数
1 | class B{ |
C++ 运算符重载
Java中的字符串String之所以能够相加,其实就是重载了+号运算符。
1 | class Point{ |
C++ 函数
默认参数
1 | // 函数默认参数 |
可变参数
1 | // 可变参数 |
常函数
1 | class B{ |
C++ 类和结构体
调用顺序
如果一个类里面存在其他类的属性对象,那么构造函数和析构函数的调用顺序为:
创建时:先调用属性对象的构造函数,在执行自己的构造函数;
销毁时:先调用自己的析构函数,再执行属性对象的析构函数;
构造函数
构造函数在对象被销毁时调用;
1 | class Student{ |
析构函数
析构函数在对象被销毁时调用;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37class Student{
private:
char* name;
int age;
public:
// 无参构造函数(会覆盖父类的无参构造函数)
Student(){
cout << "调用无参构造函数" << endl;
this->name = (char*)malloc(sizeof(char)*100);
strcpy(name, "json");
}
// 定义有参的构造函数后,默认无参构造函数将被覆盖
Student(int age, char* name){
// 字符串后面会带有0作为结束符,所以要加1
int len = strlen(name);
this->name = (char*)malloc(len + 1);
strcpy(this->name, name);
this->age = age;
}
// 对象被销毁时调用,可以做善后处理,比如,释放内存
~Student(){
cout << "调用析构函数" << endl;
free(name);
}
};
void func(){
Student t;
}
void main(){
//func();
system("pause");
}
拷贝构造函数
调用场景:
1,变量间的赋值: T t1 = t2;
2,函数调用时传参,值传递时调用;
3,作为函数返回值返回,给其他变量赋值时(与第1种情况同 )
1 | class Student{ |
浅拷贝问题
默认情况下,拷贝构造函数是浅拷贝,也就是值拷贝。当我们在构造函数中为成员变量开辟了动态
堆内存空间,进行浅拷贝后,拷贝变量也会指向同一个堆内存空间,此时,在变量销毁时,调用
析构函数,源变量和拷贝变量都会对同一内存空间进行释放,此时就会报错。
(浅拷贝是值拷贝,而指针的值是地址,所以拷贝出来都是指向同一个地址空间)1
2
3
4
5
6
7
8void copyPro(){
Student stu(10, "llll");
// stu2拷贝了stu的变量值,其成员变量name同时指向了同一个内存空间
Student stu2 = stu;
// 函数销毁时,stu和stu2都会调用析构函数去释放内存空间,导致重复释放的问题
}
深拷贝解决浅拷贝问题:
开辟一段新的内存,不只拷贝变量值,还会拷贝对应的地址内容;1
2
3
4
5
6
7Student(const Student &obj){
int len = strlen(obj.name);
// 字符串后面会带有0作为结束符,所以要加1
this->name = (char*)malloc(len + 1);
strcpy(this->name, obj.name);
this->age = obj.age;
}
C++ 类和结构体
类
1 | #define PI 3.14 |
类的大小
1 | class A{ |
结构体
1 | struct Teacher{ |
C++中的类定义步骤
1,在C++中,类和函数一般会声明在头文件中:
teacher.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// C++ 中,类和函数的声明都是放在头文件中的
// 确保该头文件在多次include时,只会被引入,编译一次
#pragma once
class MyTeacher{
private:
int age;
char* name;
public:
void setAge(int age);
int getAge();
void setName(char* name);
char* getName();
};
2,实现
teacher.cpp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include "teacher.h"
int MyTeacher::getAge(){
return this->age;
}
void MyTeacher::setAge(int age){
this->age = age;
}
void MyTeacher::setName(char* name){
this->name = name;
}
char* MyTeacher::getName(){
return this->name;
}
3,使用
1 | #include "teacher.h" |
C++ 引用和指针
引用
1 | // C++ 的标准输入,输出头文件 |
引用传递
1 | // C++ 的标准输入,输出头文件 |
指针引用
1 | void getTeacher(Teacher **p){ |
指针常量与常量指针
1 | void main(){ |
常引用
1 | void main(){ |
C++ 与C 的区别
bool
1 | // C++ 的标准输入,输出头文件 |
三元表达式
1 | // C++ 的标准输入,输出头文件 |