1. 内存分区模型
代码区:存放函数体的二进制代码,由操作系统进行管理 全局区:存放全局变量和静态变量以及常量 栈区:由编译器自动分配释放,存放函数的参数值,局部变量等 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
内存四区意义; 不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程
1.1 程序运行前 程序编译后,生成了.exe可执行程序,未执行前分为两个区域。 代码区: 存放cpu执行的机器指令 特点:代码区是共享的? 只读的 全局区: 全局变量、静态变量、常量存放在此。 该区域的数据在程序结束后由操作系统释放。 static 静态变量 常量:字符串常量 const修饰的常量 const修饰的全局变量
ps:const修饰的局部变量,不在全局区
1.2 程序运行后 栈区: 由编译器自动分配释放,存放函数的参数值,局部变量等。 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。
int* func(){
//局部变量 存放在栈区,栈区的数据在函数执行完后自动释放
int a = 10;
return &a; //返回局部变量的地址
}
编译器只会做一次保留
堆区: 由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。 在c++中主要利用new在堆区开辟内存
int* func(){
int * p = new int(10);
return p;
}
1.3 new操作符 ?c++中利用new在堆区开辟内存 ?堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符delete。 语法:new数据类型 利用new创建的数据,会返回该数据对应的类型的指针
delete p;
//在堆区利用new开辟数组
void test(){
int * arr = new int[10];
for(int i = 0; i < 10; i++){
arr[i] = i + 100;
}
//for cout<<……
delete[] arr; //释放数组要加[]
}
2. 引用 2.1 引用的基本使用 作用:给变量起别名 语法:数据类型 &别名 = 原名
//示例
int a = 10;
int &b = a; //对引用进行初始化
//注意此处,无论操纵a,b都是对同一块内存进行操作
?2.2 引用的注意事项: 1.引用必须进行初始化 2.引用进行初始化后,就不可发生改变(不可再改为其他内存块的别名)
?2.3 引用做函数参数 作用:函数传参时,可以利用引用让形参修饰实参 优点:简化指针 !!!此处划重点 值传递 不会改变实参的值,地址传递 和 引用传递 会改变实参的值
?2.4 引用做函数返回值?
1.以下代码中,编译器只会保留一次局部变量(栈区)的引用返回值即释放。
#include<iostream>
using namespace std;
int& test(){
int a = 10;
return a;
}
int main(){
int &ref = test(); //此处通过引用返回了局部变量
system("pause");
return 0;
}
?2.可通过引用返回静态变量,全局变量等
#include<iostream>
using namespace std;
int& test(){
static int a = 10;
return a;
}
int main(){
int &ref = test(); //此处通过引用返回了静态变量
system("pause");
return 0;
}
3.函数做左值时必须返回引用
//test()为上述代码块中函数
test() = 1000; //此时a 、ref为100
2.5 引用的本质? ??指针常量
//以下两句语句等效
//指针常量是指针指向不可改
int& ref = a;
int* const ref = &a;
2.6 常量引用 ?作用:修饰形参,防止误操作。 在函数形参列表中,可以加const修饰形参,防止形参改变实参
//加上const成为只读状态,不可修改
const int &r = 10; //相当于 int t = 10; const int & r = t;
int a = 10;
void test(const int &temp){ // 加const防止误操作
//val = 100;
cout << temp << endl;
}
3.函数提高 3.1 函数默认参数 函数形参列表中的形参可以有默认值
int func(int a = 1, int b = 2, string c){
//……
}
3.2 函数占位参数? c++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。 语法:返回值类型 函数名 (数据类型){ }
void func(int a, int){
cout << "this is a func" << endl;
}
3.3 函数重载
3.3.1 概述 作用:函数名可以相同,提高复用性 函数重载满足条件: 1.同一个作用域下 2.函数名称相同 3.函数参数类型不同或个数不同或顺序不同 ?
ps:函数返回值不可以作为函数重载的条件
3.3.2 函数重载注意事项 1.【引用&&const】重载详述 条件:函数名称相同,参数类型分别为为引用和const类型引用。 调用:优先调用参数(读、写)类型相同的函数
#include <iostream>
using namespace std;
void func(int &a){
cout << "func1" << endl;
}
void func(const int &a){
cout << "func2" << endl;
}
int main(){
int a = 10; // a为一个可读可写的变量
func(a); //a为一个可读可写变量,故此时优先调用func(int &a);
func(10); //func(const int &a)函数参数为const类型,只读,故此时优先调用;
return 0;
}
2.函数重载碰到默认参数 避免出现二义性 ?
4 类和对象
c++面对对象的三大特性为:封装、继承、多态。 c++认为万事万物都皆为对象,对象上有其属性和行为。 具有相同性质的对象,抽象为类。
4.1 封装
4.1.1 封装的意义
- 将属性和行为作为一个整体,表现生活中的事物
- 将属性和行为加以权限控制
封装意义一:
??将属性和行为作为一个整体,表现生活中的事物。 ? 语法:class 类名{ 访问权限:属性? ?/? ?行为 };
属性赋值:①直接赋值 ②通过行为赋值
#include<iostream>
using namespace std;
//设计一个圆类,求圆周长
const double PI = 3.14;
//class代表 设计一个类,类后面紧跟着的就是类名称
class Circle{
//访问权限
//公共权限
public:
//属性 (半径)
int m_r;
//行为
void setM_r(int r){
m_r = r;
}
//(获取周长)
double calculateZC()
{
return 2 * PI * m_r;
}
}
int main(){
//通过圆类,创建具体的圆(对象)
//实例化(通过一个类,创建一个对象的过程)
Cirlce c1;
//给圆对象的属性进行赋值
cl.m_r = 10;
//cl.setM_r(10); //通过行为给属性赋值
cout << c1.calculateZC() << endl;
system("pause");
return 0;
}
类中的属性和行为,统一称为成员。 属性:成员属性/成员变量。 行为:成员函数/成员方法 一些名词:对象、实例化 、属性、行为、成员
封装意义二: 类在设计时,可以把属性和行为放在不同的权限下,加以控制。
访问权限有三种: 1.public 公共权限? ? ? ???类内可以访问,类外可以访问 2.protected 保护权限? ? 类内可以访问, 类外不可以访问 3.private 私有权限????????类内可以访问 ,类外不可以访问
后俩类区别在继承上有所体现。
class Person{
public:
string m_Name;
protected:
string m_Car;
private:
int m_Password;
public:
void func(){
m_Name = "zhangsan";
m_Car = "tuolaji"; //类外不可以访问
m_Password = 12345; //类外不可以访问
}
}
4.1.2 struct和class的区别 ? ? 唯一区别:默认的访问权限(未声明权限类别时)不同。
4.1.3 成员属性设置为私有 优点一:将所有成员属性设置为私有,可以自己控制读写权限。 优点二:对于写权限,我们可以检测数据的有效性。
class Person{
public:
void setName(string name){
m_Name = name;
}
string getName(){
return m_Name;
}
int getAge(){
m_Age = 0;
return m_Age;
}
void setLover(string lover){
m_Lover = lover;
}
private:
//可读可写
string m_Name;
//只读
int m_Age;
//只写
string m_Lover;
}
|