知识点1.new和delete关键字
1、new和malloc(变种calloc、realloc)比较:
①malloc返回一个void指针,C++不允许将void赋值给其他任何指针,必须强转;
②malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功;
③malloc不会调用构造函数,free不会调用析构函数。
注意:new、delete和malloc、free不要混搭使用。
2、new给基本类型分配空间,delete释放空间
void test01()
{
int *p = NULL;
//给基本类型分配空间,p = (int *)calloc(1, sizeof(int));
p = new int;
*p = 100;
cout << "*p = " << *p << endl;
//释放,free p;
delete p;
}
3、new给数组类型分配空间并初始化
语法:基本类型 *变量名 = new 基本类型[数组个数];
注意,new时有[],delete释放时也必须有[]
void test02()
{
int *arr = NULL;
//给数组类型分配空间,并初始化
//arr = (int *)calloc(5, sizeof(int));
arr = new int[5]{1, 2, 3, 4, 5};
for (int i = 0; i < 5; i ++)
{
cout << arr[i] << " ";
}
cout << endl;
//释放,new时有[],释放时delete也要加[]
delete[] arr;
}
4、new从堆区实例化对象
#include <cstring>
class Student{
private:
char *Name;
int Age;
public:
Student()
{
Name = NULL;
cout << "无参构造" << endl;
}
Student(char *name, int age)
{
Name = new char[32];
strcpy(Name, name);
Age = age;
cout << "有参构造" << endl;
}
~Student()
{
cout << "析构函数" << endl;
if (Name != NULL) delete[] Name;
}
void showStudent()
{
cout << "Name = " << Name << ",Age = " << Age << endl;
}
};
void test03()
{
//new给类申请空间,如果申请成功,就会自动调用类的构造函数
Student *stu = new Student("lucy", 20);
stu->showStudent();
//delete先调用析构函数,再释放空间
delete stu;
}
结果:
5、对象数组:本质是数组,每个数组元素是类的对象
定义对象数组时,系统会给数组中的每个元素调用构造函数,未初始化时,默认调用无参构造;初始化时,初始化部分调用有参构造,未初始化部分默认调用无参构造。
void test04()
{
//对象数组
Student *stu = new Student[5]{ Student("lucy",20), Student("bob",18) };
stu[0].showStudent();
(stu + 1)->showStudent();
delete [] stu;
}
结果:
6、尽量不要使用delete释放void *,因为无法从void中寻找响应的析构函数
void test05()
{
Student *stu = new Student("lucy",17);
stu->showStudent();
//万能指针,void *
void *stu1 = stu;
delete stu1;
}
结果:
知识点2.静态成员(static定义的成员)
在类的定义中,使用static定义的成员(包括成员变量和成员函数)是静态的,成为静态成员;在类的对象创建过程中,静态成员只有一个拷贝,所有类的对象共享这个拷贝。
1、静态成员变量
静态成员变量属于某个类,为所有该类的对象所共享,必须在类中声明,在类外定义。静态数据成员不属于某个对象,在为对象分配空间时不包括静态成员所占空间。
class Data{
private:
//类的静态成员属性
static int Num;
public:
int other;
static int data;
};
//类外初始化,不需要加static
int Data::Num = 0;
int Data::data = 0;
void test01()
{
//通过类名直接访问
Data::data = 10;
cout << "Data::data = " << Data::data << endl;
//通过对象访问
Data d1, d2;
d1.data = 20;
cout << "d1.data = " << d1.data << endl;
cout << "d2.data = " << d2.data << endl;
//普通成员变量是属于对象的,只能通过对象名访问
d1.other = 100;
cout << "d1.other = " << d1.other << endl;
cout << "d2.other = " << d2.other << endl;//d2.other未初始化
//cout << "Data::other = " << Data::other << endl;//err
//静态成员也有访问权限,类外不能访问私有成员
//cout << "Data::Num = " << Data::Num << endl;//err
//cout << "d1.Num = " << d1.Num << endl;//err
}
结果:
2、静态成员函数
静态成员函数的目的是操作静态成员数据,不能访问非静态成员数据,但普通成员函数可以操作静态成员数据;静态成员函数和静态成员变量都有权限之分。
class Data{
private:
int Num;//普通成员变量
static int Other;//静态成员变量
public:
//静态成员函数
static int getOther()
{
//Num = 10;//err,静态成员函数不能访问非静态成员数据
return Other;
}
};
//静态成员变量类外定义+初始化
int Data::Other = 10;
void test01()
{
//通过类名称直接访问静态成员函数
cout << "Data::getOther = " << Data::getOther() << endl;
//通过对象名访问静态成员函数
Data d;
cout << "d.getOther = " << d.getOther() << endl;
}
结果:
3、const修饰静态成员数据时,即实现成员数据共享,又使成员数据不可改变,最好在类内部初始化;在类外部初始化时,同样需要加上const修饰。
4、案例:通过静态成员计算实例化对象个数
#include <iostream>
using namespace std;
class Data{
private:
static int Count;
public:
Data(){
Count ++;
cout << "无参构造" << endl;
}
~Data(){
Count --;
cout << "析构函数" << endl;
}
static int getCount(){ return Count; }
};
int Data::Count = 0;
int main()
{
Data ob1;
Data ob2;
{
Data ob3;
Data ob4;
cout << "实例化对象的个数:" << Data::getCount() << endl;
}
cout << "实例化对象的个数:" << Data::getCount() << endl;
return 0;
}
结果: