C++学习(3)

本文深入探讨了C++中的拷贝构造函数,包括其调用时机、深拷贝与浅拷贝的区别,以及如何避免内存异常。此外,还介绍了初始化列表、`explicit`关键字的作用以及`new`运算符在动态内存管理中的应用。同时,讲解了静态成员变量和函数的特性,并通过单例模式展示了如何确保类中只有一个实例。最后,以打印机案例展示了类中统计打印次数的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拷贝构造函数

Person(const Person & P)

Person P1(P2)或Person P1=Person (P2)

不能用拷贝构造函数初始化匿名对象

若Person(P1)等价于Person P1;写到右值可以做拷贝构造函数

拷贝构造函数调用时机

  1. 用已经创建好的对象来初始化新的对象
  2. 以值传递的方式给函数参数传值
  3. 以值得方式返回局部对象

构造函数的调用规则

  1. 若自己提供了有参构造函数,那么系统不会提供默认构造函数;但还会提供拷贝构造函数,进行简单的值拷贝,系统默认给一个类提供默认构造、拷贝构造、析构函数
  2. 当提供了拷贝构造,那系统不会提供其他构造

深拷贝和浅拷贝

浅拷贝

由系统做的简单的值拷贝,会释放堆区空间

如属性里有指向堆区空间的数据,那么简单的浅拷贝会导致重复释放内存异常

解决:自己提供拷贝构造函数进行深拷贝

初始化列表基本使用:

要有参构造初始化数据

利用初始化列表来初始化数据:构造函数后+ :属性(参数),属性(参数)

Explicit关键字作用

(隐式类型转换)Mystring str =Mystring(10)

Explicit关键字防止隐式类型转换

New运算符的使用:(不使用malloc)

所以new出来的对象都会返回类型的指针malloc韩慧void还要强转

Malloc不会调用构造,但new会调用

New是运算符;malloc是函数

New会返回一个该类型的指针,会释放堆区空间

Ddelet也是运算符,配合new使用,malloc配合free使用

用void*接受new出来的指针,会出现堆区释放的问题

通过new开辟数组一定会调用默认构造函数

Person PArray2【2】={person (1),person(2)}  ;在栈区上开辟数组,可以指定有参构造

Delete【】pArray;释放数组

静态成员变量和静态成员函数:

静态成员变量

静态关键字:static

  1. 编译阶段分配内存,所有对象共享数据;
  2. 通过对象访问属性,通过类名访问属性
  3. 有权限控制

静态成员变量必须在类中声明,在类外定义

静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间

静态数据成员可以通过类名或者对象来引用

静态成员函数:

不可以访问普通成员,会共享数据

可以通过对象访问,也可以通过类名访问

非成员静态变量,属于对象身上;非静态成员函数,不属于对象身上;静态成员变量,不属于对象身上

单例模式案例:主席

  1. 目的为了类中只有一个实例,实例不需要自己释放
  2. 将默认构和拷贝构造私有化
  3. 内部维护一个对象构造
  4. 私有化唯一指针
  5. 对外提供getinstance方法来访问这个指针
  6. 保证类中只能实例化唯一一个对象
class ChairMan
{
private:
ChairMan()
{
}
ChairMan(const ChairMan&c)
{}
public:
static ChairMan* getInstance()
{
return singleMan;
}
private:
static ChairMan * singleMan;
};
ChairMan * ChairMan::singleMan = new ChairMan;
void test01()
{
ChairMan * cm1 = ChairMan::getInstance();
ChairMan * cm2 = ChairMan::getInstance();
if (cm1 == cm2)
{
cout << "cm1 与 cm2相同" << endl;
}
else
{
cout << "cm1 与 cm2不相同" << endl;
}
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS;
}

打印机案例:对比主席案例,提供了打印功能,和统计打印次数功能

class Printer

{

private:

Printer(){ m_Count = 0; };

Printer(const Printer& p);

public:

static Printer* getInstance()

{

return singlePrinter;

}

void printText(string text)

{

cout << text << endl;

m_Count++;

cout << "打印机使用了次数为: " << m_Count << endl;

}

private:

static Printer* singlePrinter;

int m_Count;

};

Printer* Printer::singlePrinter = new Printer;



void test01()

{

Printer * printer =  Printer::getInstance();

printer->printText("离职报告");

printer->printText("入职报告");

printer->printText("加薪申请");

printer->printText("升级申请");

printer->printText("退休申请");

}
int main(){

test01();

system("pause");

return 0;

}

对象模型:

成员变量和成员属性分开处理,内部会区分

空类大小为1.每一个实例的对象都有独一无二的地址,char维护这个地址

This指针的基本使用

解决一个非内联成员函数只诞生一份实例,即为对象共用一块代码

This指针指向被调用的成员函数所属的对象

This隐含与每个类的非静态成员函数中。只有非静态成员函数才有this指针

This可以解决命名冲突,*this指向对象本体

空指针访问成员函数

如果成员函数没有用到this ,那么可以空指针直接访问;如果成员函数用到了this指针,可以加if判断,如果this为NULL会return

常函数 常对象

常函数: void func() const{};修饰的是this指针 const type * const this

常函数不能修改指针执行的值,在对象前加入const修饰 const Person p1;

常对象不能调用普通的成员函数,可以调用常函数

用mutable修饰的关键字是在常函数可以修改的

欢迎关注技术公众号,获取更多软件学习干货!

我们能为你提供什么?

技术辅导:C++、Java、嵌入式软件/硬件

项目辅导:软件/硬件项目、大厂实训项目

就业辅导:就业全流程辅导、技术创业支持

对接企业HR:培养输送优质性人才

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值