四个内存区
代码区:存放函数体的二进制代码,由操作系统管理
全局区:存放全局变量、静态变量和常量
栈区:由编译器自动分配释放,存放函数的参数和局部变量
堆区:由程序员分配和释放,弱程序员不释放,程序结束时操作系统自动回收
编译:程序编译后会生成exe可执行程序,未执行该程序前氛围两个区域
代码区:
存放cpu执行的机器指令
代码区时共享的,同一个代码生成的多个exe文件内存中只有一份代码
代码区是只读的,防止程序意外的被修改
全局区:
存放全局变量和静态变量和常量
该区域的数据在程序运行结束后由操作系统释放
栈区:
由编译器自动分配释放,存放函数的参数和局部变量
注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
堆区
由程序员分配和释放,弱程序员不释放,程序结束时操作系统自动回收
在c++中利用new在堆区开辟内存
new关键字
/*new
new关键字返回的是指针类型
*/
int* p = new int(10);
// 开辟一个数组
int* q = new int[10];
// 访问数组中的元素
q[5] = 10;
// 释放堆内存
delete p;
//释放数组
delete[] q;
引用(起别名)
// 以引用的方式接收参数
int func(int &a) {
}
int main()
{
/*引用:
数据类型 &别名=原名;
引用必须初始化
引用初始化后不可以改变
引用类型作为参数时,修改形参可以直接修改实参
*/
int a = 10;
int &b = a;
func(a);
// 常量引用
const int &a = 10;
return 0;
}
函数
/* 默认参数
如果某个位置已经有默认参数,则从这个位置后面的参数都要有默认参数
如果函数的生命有默认参数,函数的实现不能再设置默认参数
*/
int func(int a, int b=10,int c=20) {
}
/*函数的占位参数
展位参数也可以有默认参数
func(int a, int =10)
*/
int func(int a, int) {
}
类对象
对象的构造函数和析构函数
class lenclass {
/*
构造函数:可以有参数和重载
类名(){}
按参数分类:有参构造和无参构造(提供了有参构造就不会有默认无参构造)
按类型分类:普通构造和拷贝构造(提供构造函数就不会提供有参和无参)
拷贝构造函数接收一个本类的对象
三种调用方式:
括号法
显示法
隐式转换法
*/
public:
lenclass() {
}
lenclass(int a) {
}
// 拷贝构造函数
lenclass(const lenclass &P) {
}
/*
析构函数:~函数名(){}
*/
~lenclass()
{
}
};
int main() {
// 括号法
lenclass p1;
lenclass p2(10);
//拷贝调用
lenclass p3(p2);
// 匿名对象,当前行执行完之后马上释放
lenclass(10);
//显示法
lenclass p2 = lenclass(10);
// 隐式转换法
lenclass p2 = 10; //等同于lenclass p2 = lenclass(10);
}
初始化
class lenclass {
private:
int ma;
public:
//传统初始化方法
// 调用方法 lenclass p1(10)
lenclass(int a) {
ma = a;
}
//列表方法初始化
// 调用方法 lenclass p1(10);
lenclass(int a) :ma(a) {
}
};
this指针
c++中静态成员变量和成员函数并不属于对象本身,多个对象共用一组成员变量和成员函数
this指针指向被调用的成员函数所属的对象
this指针隐含每一个非静态成员函数内
当形参和成员变量同名时,可通过this指针来区分
在类的非静态成员函数中返回对象本身使用 return *this
空指针访问成员函数
class Person {
public:
void showClassName() {
cout << "this is a class name" << endl;
}
void showPersonAge() {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
int age;
int className;
};
int main() {
// 创建一个空指针
Person *person = NULL;
// 如果函数体内没有访问成员变量,则不会报错
person->showClassName();
person->showPersonAge();
}
const修饰成员函数
/*常函数
成员函数后加const后就是常函数
常函数不可修改成员属性
成员属性声明时加关键字mutable后在常函数中仍然可以修改
*/
/*常对象
生命对象前加const称为常对象
常对象只能调用常函数
*/
class Person {
public:
void showClassName() const{
cout << "this is a class name" << endl;
}
void showPersonAge() const {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
mutable int age;
int className;
};
int main() {
// 创建一个空指针
Person *person = NULL;
// 如果函数体内没有访问成员变量,则不会报错
person->showClassName();
person->showPersonAge();
}
友元
提供外部访问内部私有方法的途径
全局函数做友元
class Person {
//全局函数做友元,让goodfriend能够访问类内私有方法
friend void goodfriend();
public:
void showClassName() const{
cout << "this is a class name" << endl;
}
void showPersonAge() const {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
mutable int age;
int className;
private:
int a;
};
void goodfriend() {
// 访问私有成员
Person person;
person.a;
}
类做友元
class Person {
//类做友元,让Goodfriend类能够访问类内私有方法
friend class Goodfriend;
public:
void showClassName() const{
cout << "this is a class name" << endl;
}
void showPersonAge() const {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
mutable int age;
int className;
private:
int a;
};
class Goodfriend {
public:
// 通过visit访问Building中的私有属性
void visit();
Person *person;
};
void Goodfriend::visit() {
person->a;
}
类方法做友元
class Person {
//类做友元,让Goodfriend类能够访问类内私有方法
friend void Goodfriend::visit();
public:
void showClassName() const{
cout << "this is a class name" << endl;
}
void showPersonAge() const {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
mutable int age;
int className;
private:
int a;
};
类函数做友元
class Person {
//类函数做友元,让Goodfriend类的visit方法能够访问类内私有方法
friend void Goodfriend::visit();
public:
void showClassName() const{
cout << "this is a class name" << endl;
}
void showPersonAge() const {
// 如果是空指针访问,则结束访问
if (this == NULL)return;
cout << "age="<<age << endl;
}
mutable int age;
int className;
private:
int a;
};
运算符重载
给运算发重新进行定义,赋予其另一种功能,以适应不同的数据类型
通过成员函数重载+运算
class Person {
public:
int age;
int name;
Person operator+(Person &p) {
Person temp;
temp.age = this->age + p.age;
return temp;
}
private:
int a;
};
// 两种调用方法
p3 = p1 + p2;
p3 = p1.operator+(p2);
通过全局函数重载+
Person operator+(Person &p1,Person &p2) {
Person temp;
temp.age = p1.age + p2.age;
return temp;
}
// 两种调用方法
p3 = p1 + p2;
p3 = operator+(p1,p2);