【C++】何时需要自定义拷贝构造函数和赋值符

news/2024/7/3 7:17:21

先来说结论:当类中有指针类型成员变量的时候,一定要自定义拷贝构造和赋值运算符

原因:当我们在有指针类成员变量的时候,还是用默认拷贝构造函数(拷贝构造函数执行的时候会调用赋值符),默认赋值为浅拷贝,会导致两个对象指向同一块堆区空间,在最后析构的时候导致内存二次析构而出错!

下面来看一下代码的示例:

#include<iostream>
using namespace std;
#include<string.h>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}~SeqList() {free(data);data = NULL;}
};int main()
{SeqList seqa;SeqList seqb(seqa);return 0;
}

大家来看一下上述代码的分析以及错误原因:

 现在我们来自定义拷贝构造函数和赋值运算符:

拷贝构造函数:

SeqList(const SeqList& Seq)
{maxsize = Seq.maxsize;cursize = Seq.cursize;data = (int*)malloc(sizeof(int) * Seq.maxsize);//得在堆区重新申请一块空间来确保不会二次析构memcpy(data, Seq.data, sizeof(int)* Seq.cursize);//将seq堆区的东西拷贝
}

下面来看一下为什么还需要对赋值运算符进重写:

#include<iostream>
using namespace std;
#include<string.h>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}~SeqList() {free(data);data = NULL;}
};int main()
{SeqList seqa;SeqList seqb;seqa = seqb;return 0;
}

我们来分析一下这里错误的原因:

下面我们来自定义等号运算符:

	SeqList& operator=(const SeqList& Seq){if (this != &Seq){free(data);  //将内存泄漏那一块提前给释放了data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int) * Seq.cursize);maxsize = Seq.maxsize;cursize = Seq.cursize;}return *this;}

下面将代码整合起来:

#include<iostream>
using namespace std;
#include<Cstring>#define SIZE 10class SeqList
{int *data;int maxsize;int cursize;
private:public:SeqList() :data(NULL), maxsize(SIZE), cursize(0){data = (int*)malloc(sizeof(int) * maxsize);}SeqList(const SeqList& Seq){maxsize = Seq.maxsize;cursize = Seq.cursize;data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int)* Seq.cursize);}SeqList& operator=(const SeqList& Seq){if (this != &Seq){free(data);data = (int*)malloc(sizeof(int) * Seq.maxsize);memcpy(data, Seq.data, sizeof(int) * Seq.cursize);maxsize = Seq.maxsize;cursize = Seq.cursize;}return *this;}~SeqList() {free(data);data = NULL;}
};int main()
{/*SeqList seqa;SeqList seqb(sqea);*/SeqList seqa;SeqList seqb;seqa = seqb;return 0;
}

总结一下,当类中有指针类型成员变量的时候,一定要自定义拷贝构造和赋值运算符,否则会造成内存泄漏或者二次析构!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pgtn.cn/news/15595.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

iOS自动布局一

Align: Pin&#xff1a; 转载于:https://www.cnblogs.com/123qw/p/4404167.html

【C++】左值、右值、移动拷贝构造函数、移动赋值函数

左值和右值的定义以及区别: 先来看在C语言中的左值和右值 &#xff1a; 左值&#xff1a;可赋值的值为左值 右值&#xff1a;不可赋值的值为右值 再来看C中左值右值的定义如下&#xff1a; 左值&#xff1a;可以取地址的值&#xff08;有名字的值、非临时量&#xff09; …

【C++】typedfe和宏定义的区别

先来说结论&#xff1a; 1.宏定义作用于编译之前(也就是预编译阶段&#xff0c;而typedef作用于编译阶段 2.typedef仅限于类型的重定义&#xff0c;而宏定义不仅可以为类型起别名还可以为数值定义起别名(简单的替换) 下面来看一下区别 下面这是typedef的用法 typedef int* PI…

GPS部标平台的架构设计(十)-基于Asp.NET MVC构建GPS部标平台

在当前很多的GPS平台当中&#xff0c;有很多是基于asp.NETsiverlight开发的遗留项目&#xff0c;代码混乱而又难以维护&#xff0c;各种耦合和关联&#xff0c;要命的是界面也没见到比Javascript做的控件有多好看&#xff0c;随着需求的增多&#xff0c;平台已经臃肿不堪。 设计…

【C++】虚函数

虚函数是构成C多态的重要一步&#xff0c;今天来说一下虚函数&#xff01; 虚函数&#xff1a; 在基类(或父类)中&#xff0c;使用virtual关键字对函数进行声明为并在一个或多个派生类(子类)中被重新定义的成员函数&#xff0c;通过指向派生类的基类指针或引用&#xff0c;访…

看了极光推送技术原理的几点思考

看了极光推送技术原理的几点思考 分类&#xff1a; android2012-11-26 20:50 16586人阅读 评论(18) 收藏 举报目录(?)[] 移动互联网应用现状 因为手机平台本身、电量、网络流量的限制&#xff0c;移动互联网应用在设计上跟传统 PC 上的应用很大不一样&#xff0c;需要根据手机…

【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数

我们都知道面向对象编程的三大特征是封装、继承、多态&#xff0c;今天我们就来说一下其中之一的多态。 概念&#xff1a; 多态&#xff1a; 多态字面意思就是多种形态&#xff0c;C 多态意味着调用成员函数时&#xff0c;会根据调用函数的对象的类型来执行不同的函数。(取自…

【C++】多线程thread

进程和线程这部分呢我之前在我Linux中写过这些东西&#xff0c;和C中线程的概念差不多&#xff0c;大家可以去看一下&#xff1a; Linux多线程_神厨小福贵&#xff01;的博客-CSDN博客进程和线程的区别有哪些呢&#xff1f;进程是资源分配的最小单位&#xff0c;线程是CPU调度…