1,内存分区
C++程序在执行时,将内存大方向划分为4个区域
a,代码区:存放函数体的二进制代码,由操作系统进行管理的
b,全局区:存放全局变量和静态变量以及常量
c,栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
d,堆区:由程序员分配和释放,若程序员不释放,程序结束由操作系统回收
1.1程序运行前
在程序编译后,未执行该程序前分为两个区域
a,代码区:存放CPU执行机器指令
特点:共享的,只读的
b,全局区
全局变量和静态变量存放在此还包含了常量区,字符串常量(“jkl”),和其他常量都存放在此
1.2程序运行后
栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
堆区:由程序员分配和释放,若程序员不释放,程序结束由操作系统回收.
堆区由new开辟空间,delete关键字释放空间
#include<iostream>
using namespace std;
char *func()
{
char *p1 = new char('a');
cout<<*p1<<endl;
return p1;
}
int *array2()
{
int *p2 = new int[10];
cout<<"geshu"<<sizeof(p2)/sizeof(int)<<endl;
for(int i =0;i<10;i++)
{
p2[i] = 10+i;
}
for(int i =0;i<10;i++)
{
cout<<p2[i]<<endl;
}
return p2;
}
int main()
{
char *p1 = func();
int *p2 = array2();
cout<<*p1<<endl;
cout<<*p1<<endl;
int a[10];
cout<<"geshu"<<sizeof(a)/sizeof(int)<<endl;
for(int i =0;i<10;i++)
{
cout<<p2[i]<<endl;
}
delete[] p2;
delete p1;
return 0;
}
2.1,C++引用
C++里面的引用实际是一个指针常量,最重要的是在函数里面引用
注意不要返回局部引用
eg:
#include<iostream>
using namespace std;
void func1(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
cout<<"func1:a="<<a<<" b="<<b<<endl;
}
void func2(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
cout<<"fun2:a="<<*a<<" b="<<*b<<endl;
}
void func3(int a,int b)
{
int temp=a;
a=b;
b=temp;
cout<<"func3:a="<<a<<" b="<<b<<endl;
}
int main()
{
int a=10;
int b=20;
func1(a,b);
cout<<"a="<<a<<" b="<<b<<endl;
func2(&a,&b);
cout<<"a="<<a<<" b="<<b<<endl;
func3(a,b);
cout<<"a="<<a<<" b="<<b<<endl;
return 0;
}
2.2,C++中函数升级版
注意:在函数声明中给形参赋值了以后,不能在函数头中在一次赋值。在给其中一个形参赋值后那么后面的形参都得赋值。
#include<iostream>
using namespace std;
int func2(int a=20,int b=50,int c=50);
int func1(int a,int b=10,int c=20,int d=50)
{
return a+b+c+d;
}
int func2(int a,int b,int c)
{
return a+b+c;
}
int main()
{
cout<<func1(10)<<endl;
cout<<func1(10,10,10,10)<<endl;
cout<<func2()<<endl;
return 0;
}
2.3函数重载
作用:函数名可以相同,提高复用性
a,在同一个作用域下
b,函数名相同
c,函数的形参个数,位置,变量类型至少有一个不一样
#include<iostream>
using namespace std;
int func1(const int &b = 10)//常量引用
{
cout<<"ok1"<<endl;
}
int func1(int &a)
{
cout<<"ok2"<<endl;
}
int main()
{
func1(10);
return 0;
}
3,类与对象
C++面向对象的三大特性为:封装,继承,多态;C++对万事万物都皆为对象,对象上有其属性和行为。
3.1封装
意义:将属性和行为作为一个整体,表现一个事物;将属性和行为加以权限控制
类中的属性和行为 我们统称为成员
属性 :成员属性 成员变量
行为 成员函数 成员方法
#include<iostream>
using namespace std;
class stu
{
public:
int ID;
string name;
public:
void show()
{
cout<<"name:"<<name<<" ID: "<<ID<<endl;
}
void getID(int s_ID)
{
ID=s_ID;
}
void getName(string s_name)
{
name=s_name;
}
};
int main()
{
stu a1;
int a;
string name;
cin>>a;
cin>>name;
a1.getID(a);
a1.getName(name);
a1.show();
a1.ID=3;
a1.name="poly";
a1.show();
return 0;
}
权限:有三种
a,公共权限 public 成员 类内可以访问,类外可以访问
b,保护权限 protected 成员 类内可以访问,类外不可以访问,儿子可以访问
c,私有权限 private 成员 类内可以访问,类外不可以访问,儿子不可以访问
3.2,C++中struct和class唯一的区别就在于默认权限不同,struct默认公共权限,class默认为私有权限
3.3,私有权限
W:可写
R:可读
X:可执行
#include<iostream>
#include<string>
using namespace std;
class person
{
public:
void setName(string name)//W
{
m_name = name;
}
string getName()//R
{
return m_name;
}
int getAge()//R
{
m_age = 10;
return m_age;
}
void setWife(string wife)//W
{
m_wife = wife;
cout<<"finishing"<<endl;
}
private:
string m_name;//W and R
int m_age;//R
string m_wife;//W
};
int main()
{
person lora;
lora.setName("lora");
cout<<"name:"<<lora.getName()<<endl;
cout<<"age:"<<lora.getAge()<<endl;
lora.setWife("lucy");
return 0;
}
3.3构造函数与析构函数
构造函数:主要作用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
析构函数:主要作用于在对象销毁前系统自动调用,执行一些清理工作。
注意:构造函数
a,没有返回值,不用写void.
b,函数名与类名相同
c,构造函数可以有参数,可以发生重载
d,创建对象的时候,构造函数会自动调用,而且只调用一次
析构函数
a,没有返回值,不写VOID.
b,函数名与类名相同在名称前加~
c,析构函数不可以有参数的,不可以发生重载
d,销毁对象的时候,析构函数会自动调用,而且只调用一次
构造函数与析构函数如果我们没有创建,但是系统会帮我们创建也就是说必须有的
3.3.1构造函数分类与调用
两种分类方式:
按参数分为:有参构造和无参构造
按类型分为:普通构造和拷贝构造
三种调用方式
a,括号法
b,显示法
c,隐式转换法
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout<<"this is not parameter of function of construction"<<endl;
}
Person(int a)
{
m_num=a;
cout<<"this is parameter of function of construction"<<endl;
}
Person(const Person &a)
{
m_num=a.m_num;
cout<<"copy of the function of construction"<<endl;
}
~Person()
{
cout<<"Destruction of the function"<<endl;
}
public:
int m_num;
};
int main()
{
//Anonymous target
Person(20);
//the construction of the function of the way of()
Person a;
Person a1(10);
Person a2(a1);
cout<<"a1.m_num="<<a1.m_num<<endl;
cout<<"a2.m_num="<<a2.m_num<<endl;
//the construction of the function of the way of showing
Person b;
Person b1 = Person(12);
Person b2 = Person(b1);
cout<<"b1.m_num="<<b1.m_num<<endl;
cout<<"b2.m_num="<<b2.m_num<<endl;
//the construction of the function of the way of showing
Person c1 = 10;
Person c2 = c1;
return 0;
}
注意:括号法不要这样写person a1();这代表一个函数声明
不要用拷贝构造来写匿名构造函数,编译器会认为是定义了一个对象
3.4,拷贝函数的调用时机
a,使用一个已经创建完毕的对象来初始化一个新对象
b,值传递的方式给函数参数传值
c,以值的方式返回局部对象
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"construction"<<endl;
}
person(int a)
{
m_a = a;
cout<<"construction"<<endl;
}
person(const person &p)
{
m_a=p.m_a;
cout<<"this is copy"<<endl;
}
~person()
{
cout<<"destruction"<<endl;
}
public:
int m_a;
};
//using inited target;
void test()
{
person a;
person b(10);
person c(b);
cout<<"c.m_a "<<c.m_a<<endl;
}
//the value give the functional the value
void test01(person p)
{
}
void test02()
{
person p;
test01(p);
}
//using the value return to part of the target
person aj()
{
person p(10);
cout<<(int *)&p<<endl;
return p;
}
void test03()
{
person p1 = aj();
cout<<(int *)&p1<<endl;
}
int main()
{
// test();
// test02();
test03();
return 0;
}
3.5,构造函数调用规则
默认情况下,C++编译器至少给一个类添加3个函数
1,默认构造函数(函数体为空)
2,默认析构函数(无参,参数体为空)
3,默认拷贝构造函数,对属性进行拷贝
注意:如果有了1那么其他两个需要自己配置,如果有2,那么1没有,3有,如果有3,则只有3.
eg:
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"this is default construction of function"<<endl;
}
person(int age)
{
m_age = age;
cout<<"this have parameter construction of function"<<endl;
}
~person()
{
cout<<"this is destruction of function"<<endl;
}
person(const person &a)
{
m_age =a.m_age;
cout<<"this copy construction of function"<<endl;
}
void test01()
{
person a(10);
person b(a);
cout<<b.m_age<<endl;
}
public:
int m_age;
};
void test01()
{
person b(10);
person c(b);
cout<<b.m_age<<endl;
}
int main()
{
test01();
// b.test01();
return 0;
}
3.6,话说浅拷贝与深拷贝
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间进行拷贝操作
如果属性有在堆区开辟空间的一定要自己写拷贝构造函数避免发生对一个空间进行释放两次的非法操作。
eg:
#include<iostream>
using namespace std;
class person
{
public:
person()
{
cout<<"this is default construction of function"<<endl;
}
person(int age,int hight)
{
m_age = age;
m_hight = new int(hight);
cout<<"this have parameter construction of function"<<endl;
}
~person()
{
if(m_hight!=NULL)
{
delete(m_hight);
}
cout<<"this is destruction of function"<<endl;
}
person(const person &a)
{
m_age =a.m_age;
m_hight = new int(*(a.m_hight));
cout<<"this copy construction of function"<<endl;
}
public:
int m_age;
int *m_hight;
};
void test01()
{
person a(10,180);
person b(a);
cout<<"a:"<<a.m_age<<*(a.m_hight)<<endl;
}
int main()
{
test01();
return 0;
}
3.7,初始化列表
作用:C++提供了初始化列表语法,用来初始化属性:
eg:
#include<iostream>
using namespace std;
class person
{
public:
person(int a,int b,int c):A(a),B(b),C(c)
{
}
public:
int A;
int B;
int C;
};
int main()
{
person b(10,20,30);
cout<<b.A<<endl;
cout<<b.B<<endl;
cout<<b.C<<endl;
return 0;
}