c++三大函数:拷贝构造(copy ctor)、拷贝赋值(copy op)、析构函数(dtor)

article/2025/9/24 21:54:41

Class的两个经典分类

  • Class without pointer member(s)
    complex
  • Class with pointer member(s)
    string

String class
以下为头文件string.h内容

#ifndef _MYSTRING_
#define _MYSTRING_
//类中进行字符串的构造
class String
{
...
}; //谨记切勿忘分号
//字符串所具备的功能
String::function(...) ...Global-function(...) ...#endif

应用拷贝构造和拷贝赋值
以下为string-test.cpp

int main()
{	String s1();String s2("hello");//拷贝构造,以s1为初值设置到s3上String s3(s1);cout << s3 <<endl;//拷贝赋值,s2赋值给s3s3 = s2;cout << s3 <<endl;
}

Note

  • 对于用class with pointer member(s)这种编译器给的一套拷贝构造和拷贝赋值,会有不好的影响,假如现在有一个对象,它里面有一个指针,指向另外一个地方,我现在又产生新的对象,如果只是拷贝,那就是指针拷贝过来,它们两个指到同一个地方去,所以只要class里边带指针,一定不能用编译器给的默认版本,一定要自己写

Big Three三个特殊函数

class String
{public://Big Three,三个特殊函数String(const String& str);				//拷贝构造String& operator=(const String& str);   //拷贝赋值~String();								//析构
};

class String的具体内容

class String
{	//只要类带指针,就一定要写出拷贝构造和拷贝赋值public:String(const char* cstr = 0 );//接收自己的引用String& ,拷贝构造String(const String& str);//操作符=重载(拷贝赋值动作)String& operator=(const String& str);//析构函数//当这个类的对象死亡的时候,就会调用析构函数~String();//一般成员函数,这个函数为内联函数char* get_c_str() const { return m_data; }//返回指针,并没有改变数据m_data的value所以函数要加cosntprivate:char* m_data;
};//谨记切勿忘分号

一般而言,都会对字符串作出以下设计
==让字符串里有一个指针,==在需要内存的时候,才创建另一个空间(例下面的hello所占的空间)去放字符本身,字符本身有大有小(hello有5个字符,helloworld有10个字符)有时候是空字符串,这样的设计有动态的感觉.而不要在class的private中放一个数组,那这个数组要设定多大呢?10000?300?所以需要一种动态分配的方式,即指针。不能用编译器给我们的拷贝构造、拷贝赋值,要自己写一套(例如上述代码public: String(const…)…的构造函数)


ctor和dtor(构造函数和析构函数)

  • 字符串是什么,就是指针指着头,后面一串,最后有一个结束符\0
//字符串构造函数
inline
String::String(const char* cstr = 0)
{	//检查传进来的字符是0吗?if(cstr){ //传入的字符非空,即指定了初值。有[中括号]的叫array newm_data = new char[strlen(cstr)+1];//动态分配空间,+1存放结束符strcpy(m_data, cstr);}else {//传入的字符为空,即未指定初值m_data = new char[1];//new分配一块内存,分配1个字符*m_data = '\0';// 结束符\0}
}
//构造析构函数,作用关门清理,释放动态分配的内存,防止内存泄漏
inline
String::~String()
{	//array new 要搭配 array delete不然会出错delete[] m_data;//有[中括号]的这种叫array delete
}

应用

  • 以下程序调用三次构造函数,三次析构函数
{String s1();String s2("hello");//m_data = new char[strlen(cstr)+1]String* p = new String("hello");//为hello动态分配6个字符的内存(包括结束符)delete p;
}

array new 一定要搭配 array delete

  • array new (本例中 m_data = new char[strlen(cstr)+1] ; )
  • array delete(本例中delete[] m_data;//[ ] 表明要删除的是数组,而不是一个字符,唤起3次析构函数,把动态分配的内存删掉)

class with pointer members必须有copy ctor和copy op

  • 以下为浅拷贝:默认拷贝构造函数将会拷贝指针,会造成内存泄漏(memory leak)
    将对象a的内容拷贝到对象b,对象b的指针由原来指向W变成现在指向H,所以现在没有指针指向W,造成了内存泄漏
String a("Hellio");
String b("World");
b = a;//这里是浅拷贝,对象b的指针指向H,但没有指针指向W,造成了内存泄漏
//什么是深拷贝呢?就是我们要写的copy ctor拷贝构造


copy ctor(拷贝构造函数)

以下程序strcpy为深拷贝:自定义拷贝构造函数将会拷贝对象的内容

inline
String::String(const String& str)
{	//str.m_data直接取另一个对象的private data(兄弟之间互为friend)m_data = new char[ strlen(str.m_data) + 1];strcpy(m_data,str.m_data);//深拷贝,把对象str内容拷贝到m_data
}

应用

{String s1("hello");String s2(s1);//以s1为初值创建出s2String s2 = s1;//意思与上一行完全相同,把s1赋值到s2上,注意s2是新创建的对象,所以需要调用构造函数
}

copy assignment operator(拷贝赋值函数)

  • a=b,对象a和b中有内容,将b的内容赋值到a之前
    [1]应该先把a中的内容删除
    [2]然后创建出与右边一样大的空间
    [3]再把右边赋值到左边
inline //成员函数,参数内隐藏this
String& String::operator = (const String& str)//重载操作符=即赋值
{	//this对应下面应用中s2=s1的s2,str对应s1if (this == &str)//检测是否为自我赋值(self assignment)看这两个指针是否指的同一个东西return *this;//如果检测结果是自我赋值,则不进行以下步骤delete[] m_data;//该操作对应上面描述文字[1]m_data = new char[ strlen(str.m_data) + 1 ];//该操作对应上面描述文字[2],+1放置结束符strcpy(m_data, str.m_data);//该操作对应上面描述文字[3]return *this;
}

应用

{String s1("hello");String s2(s1);//赋值操作s2 = s1;
}

以下为a=b赋值过程

对象a与b中已存放内容

第一步:

delete[] m_data;

删除对象a的内容

第二步:

m_data = new char[ strlen(str.m_data) + 1 ]

分配一个与右边一样大空间

第三步:

深拷贝

strcpy(m_data, str.m_data);

将对象b的内容赋值给a


一定要在operator=中检查是否self assignment

  • 写检查自我赋值不只是为了效率,也是为了正确性
    在这里插入图片描述
    [???处含义为将左边对象内容删除]
    笔记来源:
    https://www.bilibili.com/video/BV1aW411H7Xa?p=7

http://chatgpt.dhexx.cn/article/kI0x0rdE.shtml

相关文章

copy ctor、copy assignment(拷贝构造函数和拷贝赋值函数)

这个很早就搞明白了&#xff0c;只是这里系统整理一下。 例1&#xff1a; #include<iostream> using namespace std; class Test { public:Test(int test_data 0) :test_data(test_data){cout << "ctor" << endl;}Test(const Test&obj) { c…

2022-2-13 转换函数(conversion function) non-explicit-one argument ctor explicit-one argument ctor

学习时间及标题&#xff1a; 2022-2-13 转换函数(conversion function) non-explicit-one argument ctor explicit-one argument ctor 学习内容&#xff1a; 1.转换函数(conversion function)&#xff1a; 这是一个将分数(Fraction)类型转化为double类型的例子。我们可以看出…

java ctor_.ctor,.cctor 以及 对象的构造过程

.ctor&#xff1a; 简述&#xff1a;构造函数&#xff0c;在类被实例化时&#xff0c;它会被自动调用。 当C#的类被编译后&#xff0c;在IL代码中会出现一个名为.ctor的方法&#xff0c;它就是我们的构造函数&#xff0c;对应C#中的构造函数。且看下面的代码&#xff1a; publi…

Hive基础sql语法

原文:https://www.cnblogs.com/HondaHsu/p/4346354.html 1.先建 表 drop table sfmk.xzz_0726_srcarea_desarea; create table sfmk.xzz_0726_srcarea_desarea ( srcarea_desarea string ) row format delimited fields terminated by ,;2.将数据上传至hive 服务器 如&#xf…

内容耦合 c语言例子,耦合性 内聚加实例

基本信息 耦合性(或称"耦合度") 英文 : coupling 耦合性也叫块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块之间越独立则越差,模块间耦合的高低取决于模块间接口的复杂性,调用的方式以及传递的信息。 形…

[架构之路-183]-《软考-系统分析师》-13-系统设计 - 高内聚低耦合详解、图解以及技术手段

目录 第1章 什么是高内聚低耦合 1.1 概念 1.2 目的 1.3 什么时候需要进行高内聚低耦合 1.4 什么系统需要关注高内聚、低耦合 第2章 分类 2.1 内聚的分类 2.2 耦合的分类 第3章 增加高内聚降低耦合度的方法 3.1 增加高内聚 3.2 降低耦合度 第1章 什么是高内聚低耦…

java 高内聚低耦合_关于高内聚低耦合概念的理解

概念 高内聚低耦合&#xff0c;是软件工程中的概念&#xff0c;是判断软件设计好坏的标准&#xff0c;主要用于程序的面向对象的设计&#xff0c;主要看类的内聚性是否高&#xff0c;耦合度是否低。 目的 使程序模块的可重用性、移植性大大增强。 通常程序结构中各模块的内聚程…

lea 指令的小解

LEA指令的功能是将源操作数、即存储单元的有效地址&#xff08;偏移地址&#xff09;传送到目的操作数。 官方8086的白皮书&#xff0c;我的英语水平有限&#xff0c;只找到如下内容&#xff1b; ^offset和 Lea 伪指令 &#xff1b; offset 此为一个伪指令&#xff0c;它不会有…

X86 LEA指令详解

1.SDM指令功能描述(LEA) LEA 总体描述&#xff1a; 从第二个操作数&#xff08;源操作数&#xff09;计算有效地址&#xff0c;并将结果存入第一个操作数&#xff08;目的操作数&#xff09;。源操作数是指定了一种访存操作的内存地址&#xff0c;目的操作数为一个通用寄存器…

css3围绕旋转动画js特效

下载地址 css3围绕旋转动画特效&#xff0c;两种旋转方式&#xff0c;自转和公转&#xff0c;css3按照固定的轨迹行驶。 dd:

HTML5 - 用CSS3动画制作场景切换效果(移动,旋转,淡入淡出等)

两个场景&#xff08;即两个div视图&#xff09;切换的时候&#xff0c;如果想添加个过渡动画&#xff0c;除了可以使用js来实现&#xff0c;还可以通过CSS3的animation属性来实现。 &#xff08;注意&#xff1a;Internet Explorer 9 以及更早的版本不支持 animation 属性。&…

CSS3 元素转圈动画 (元素旋转动画)

CSS3 元素转圈动画 &#xff08;元素旋转动画&#xff09; <!DOCTYPE html> <html> <head> <style> div { width:100px; height:100px; background:red; position:relative; animation:mymove 5s infinite; -webkit-animation:mymove 5s infinite; /*…

css3 animation动画360旋转。旋转效果用transform:rotate过渡。

旋转&#xff1a; <div class"lds-hourglass"></div> .lds-hourglass {display:inline-block;position:relative;width:72px;height:72px } .lds-hourglass:after {content:" ";display:block;border-radius:50%;width:0;height:0;margin:6p…

css的rotate3d实现炫酷的圆环转动动画

1.实现效果 2.实现原理 2.1 rotate3d rotate3d&#xff1a;rotate3d() CSS 函数定义一个变换&#xff0c;它将元素围绕固定轴移动而不使其变形。运动量由指定的角度定义; 如果为正&#xff0c;运动将为顺时针&#xff0c;如果为负&#xff0c;则为逆时针。 语法&#xff1a; …

CSS3实现3d图片旋转动画效果

1.实现原理 1.首先所有的图片的容器position:absolute&#xff0c;叠加在一起&#xff0c;然后一次设置rotateY分别为&#xff08;36*i&#xff09;deg &#xff0c;i取0到10 &#xff1b;所有图片会相交成一个类似花的形状 然后为每个图片的容器设置translateZ&#xff0c;所有…

CSS3实现立体旋转动画效果

问题描述 一个3D立体图形在网页中呈现旋转效果,看起来十分炫酷,这个过程的实现其实并不困难,只需要利用CSS3动画效果,并对属性设置合适的参数之后,效果就能实现了。 在解决问题之前,需要先了解CSS3的动画效果是什么,其相关属性和参数有什么含义,这个过程就请查看CSS3动…

css3d动画:平移、旋转、缩放

1、前言&#xff1a; 3d比2d多了一个z轴&#xff0c;这个z轴是垂直我们屏幕的方向&#xff0c;指向我们人眼的是正轴&#xff0c;远离人眼的是负轴&#xff0c;图示如下&#xff1a; 2、景深设置和3d平移 当我们在z轴上向正轴方向上移动物体&#xff0c;也就是向我们眼前移动…

使用css3属性做一个循环旋转的动画

做这个动画是使用css3中的animation 和 @-webkit-keyframes 组合使用来完成 //这是html部分代码 <div class="home"><imgalt="logo"src="http://b-ssl.duitang.com/uploads/item/201206/26/20120626190359_MjB3s.jpeg"id="images…

基于HTML5+CSS3的图片旋转、无限滚动、文字跳动特效

本文分享几种基于HTML5CSS3实现的一些动画特效&#xff1a;图片旋转、无限滚动、文字跳动;实现起来均比较容易&#xff0c;动手来试试! 一、图片旋转 效果图如下&#xff1a; 这个效果实现起来其实并不困难。代码清单如下: <style type"text/css"> #liu{ wid…

内存碎片产生原因及终极解决办法

内存碎片通常分为内部碎片和外部碎片&#xff1a; 1. 内部碎片是由于采用固定大小的内存分区&#xff0c;当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片&#xff0c;通常内部碎片难以完全避免&#xff1b; 2. 外部碎片是由于某些未分配的连续内存区域太小&…