【高质量C++/C总结12】拷贝函数C++标准库复数类string解析

C++ 标准库中的复数类 参考: http://www.cplusplus.com/reference/complex/complex/ #include<complex> #include<iostream> using namespace :: std; int main(){ std::complex<double> cnum1; std::complex& 阅读详情

说在开始

作者:尹豆(憨豆酒),联系我yindou97@163.com,熟悉图形学,图像处理领域,本章代码: https://github.com/douysu/computer-graphics-notes

我提炼了《C++ Primer》、《侯捷C++》、《高质量程序设计指南——C/C++语言》等资料中的重要部分,并总结成此博文。其中涉及到许多我个人对C++的理解,如若有不合理之处,还请朋友们多多指出,我会虚心接受每一个建议。

观看了侯捷老师有关于拷贝构造和拷贝赋值的方法,其中涉及到浅拷贝,深拷贝等问题,当然在看本节部分的时候可能会产生很多的问题,我也是如此,产生问题的原因是因为对C/C++的内存管理机制掌握不好,当掌握了C/C++内存管理的机制后这些问题就会迎刃而解了。我也会写一篇关于C/C++内存管理机制的博客的。在这里进行总结。

本节解析了C++标准库当中的string类,自己用代码实现了,当然这里是阉割版,因为C++标准库当中的string功能实在是太复杂了,这里实现了几个简单的string的构造函数,拷贝函数等。

我们应当时刻注意一点:当我们设计的类当中有指针的时候,一定要时刻注意内存泄露,野内存等问题,也就是当类中有指针的时候,我们应该时刻注意。
如果自己的类当中含有指针,不可以使用编译器默认的拷贝函数,接下来我将会解释为什么不可以使用默认器的拷贝函数。

代码部分

先给出代码,看一下整个string类的基本架构吧,然后才好理解下面的概念问题,同样,侯捷老师把函数的实现代码放到了头文件当中,当然他使用了inline,大家需要注意.h文件用来声明是不进行编译的。
String.h

#ifndef _MY_STRING
#define _MY_STRING
class String
{
public:
	String(const char * cstr=0);//满足 String s1("hellow")的构造方式
	String(const String& str);//满足 String s1(s2)的构造方式
	String& operator = (const String& str);//满足 s1=s2的方式 
	~String();
private:
	char * m_data;//自己的数据数组
};
#include <cstring>
inline String::String(const char * cstr)//构造函数,满足 String s1("hellow")的构造方式
{
	if (cstr) {//判断是不是0
		m_data = new char[strlen(cstr) + 1];
		strcpy(m_data, cstr);
	}else {
		m_data = new char[1];
		*m_data = '\0';
	}
}
inline String::String(const String& str)//构造函数,满足 String s1(s2)的构造方式
{
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data, str.m_data);
}
inline String::~String()//析构函数
{
	delete[]  m_data;
}
inline String& String::operator =(const String& str){
	if(this==&str){//检测自我赋值 
		return *this;
	}
	delete[] m_data;
	m_data = new char[ strlen(str.m_data) + 1 ];
   	strcpy(m_data, str.m_data);
   	return *this;
}
#endif //_MY_STRING

main.cpp

#include <iostream>
#include "String.h"
using namespace std;
int main() {
	String s1("hello"); //第一种构造方式
    String s2("world"); 
    String s3(s2);//第二种构造方式
	/*
		两种构造方式:
		1、此时的s1是不存在的,直接将hello给s1
		2、第二种方式,s2和s3都是存在的,将s2的内容传递给s3
	*/
    s3 = s1;//把s1的值拷贝给s3,这里重载了操作符“=”,所以才可以完成,否则出现浅拷贝问题,稍后解释,继续往下看。
	cin.get();
	return 0;
}

几个概念

浅拷贝

如果自己使用系统的拷贝函数。也就是直接赋值=。会出现以下的错误结果:浅拷贝

从图中可以看到有两个String 对象 a和b ,其中a当中的data指针指向的是“Hello”,b的data指针指向的是“Wordld”。当使用系统的a=b时,会出现图片下半部分的错误。也就是a和b两个对象中的指针会同时指向“Hello”

这样会带来两个问题:

1、造成内存泄露,两个data指针同时指向一个区域,“world”区域没有进行释放。
2、a,b两个对象中的data指针同时指向一个区域,操作可能会出现错误。

深拷贝

这里使用了C原来的拷贝函数,首先动态分配了一块内存,然后将另一个字符串中的内容拷贝到新分配的内存中 。我使用VS2015使用这段代码的时候会提示该方法可能会出现安全性错误,建议使用strcpy_s,但是使用C-Free这种轻量行的编译器就不会出现这种错误。我的猜想有以下两点
1、C-Free比较轻量,VS适用于大型项目的开发,比较严谨。
2、C-Free更加倾向于C语言,对于C++语言的完善的可能不是很好。

拷贝赋值函数

可以看出,此块代码是重载了操作符“=”也就是s1=s2所做的事情,这个方法也是比较重要的方法。其大致可以分为两大部分。
1、首先释放this指针指向的内容,然后分配一块与str指向的大小相同的内存区域,然后在进行深拷贝。
2、其中还有检测自我赋值的内容,这里应该时刻注意。如果检测到是自己赋值给自己,那么什么都不要做,直接返回,效率更高
3、如果不写自我检测可能会出现的错误结果:

去掉自我检测部分的代码,一步步分析:
前提,两个指针都是指向的Hello,当执行第一句代码delete[] m_data;后,两个指针指向的都是空内容,此时m_data = new char[ strlen(str.m_data) + 1 ];就无法处理。应该时刻注意。

最后

如果觉得文字内容不好理解的话,大家可以想看视频资源的话,可以 VX qq619192323。有什么错误还希望大家指出,一起共同进步。
如果您喜欢C++,喜欢3D,并且想了解一点深度学习的知识,加入我们的QQ群,群里面全都是年轻的开发者,欢迎大家的加入讨论。就说是优快云过来的就行。
在这里插入图片描述

C++仿函数深度解析:从STL应用到高阶编程实践 在C++编程中,可调用对象是实现算法复用和逻辑封装的核心概念。仿函数通过重载operator()运算符,将函数行为与对象特性相结合,其原理在于将状态和行为封装在类实例中,实现了比普通函数更强的表达能力。这一技术价值在于它完美支持策略模式和高阶函数,是连接面向对象与泛型编程的关键桥梁。在应用场景上,仿函数广泛用于STL算法定制、回调系统构建以及需要携带状态的复杂业务逻辑中。本文以STL算法和策略模式为例,深入探讨了仿函数在C++泛型编程中的高级应用,特别是如何通过模板化和状态管理实现代码的高度复用与解耦。 阅读详情

相关推荐

【高质量C++/C总结9】复数类complex解析

说在开始 最近用了两天时间在侯捷老师的带领下学习了C++标准库中的复数类complex,收获真的巨多。其中涉及许多C++的知识点和细节,包括构造函数初始化的写法、const的用法,变量作用域的使用、友元函数、内联函数、运算符的重载、如何提高C++代码的执行效率、如何提高自己的C++类的的通用性等等自己掌握了很多C++的细节和面向对象的知识。讲的真的好,不愧是C++的专家。所有代码都可以在我的gi...

尹豆的博客 1600

c语言字符串转复数,C语言版--复数的实现

#includetypedef float * Complex;Status InitComplex(Complex &C,float r1,float r2){C=new float[2];if(!C) return OVERFLOW;C[0]=r1;C[1]=r2;return OK;}Status DestoryComplex(Complex &C){delete[] C;r...

weixin_42507868的博客 387

保姆级教程:在摩尔线程MTT S80上快速部署Ollama运行DeepSeek R1模型(附性能测试)

本文提供了一份详细的保姆级教程,指导用户在摩尔线程MTT S80显卡上部署Ollama并运行DeepSeek R1模型。内容涵盖从驱动安装、Docker环境配置到模型拉取、性能测试的全流程,并分享了实测数据与优化技巧,旨在帮助开发者快速在国产GPU平台上实现高效的大语言模型推理。

weixin_29091837的博客 520

标准C++复数运算类详解及使用例程

在C++中复数运算可以通过两种方式来实现:     1)标准C++复数运算库:complex ObjectName(realPart, imagePart);     2)自定义复数运算类:包括复数的实部、虚部、四则运算、模运算、共轭等。     后者可以根据需要自己定义,关于类的定义这里不再说明,具体的功能可以根据自己的需要去实现。这里介绍C++标准的复数运算类complex,网上已经有一

Qingyang8513的专栏 3万+

基于OpenAI Agents构建多智能体工作流:从原理到实战

多智能体系统(Multi-Agent System)是人工智能领域的重要分支,它通过多个智能体(Agent)的协作与交互,解决单一智能体难以处理的复杂任务。其核心原理在于将任务分解、分配与协调,每个智能体具备特定能力,通过通信机制实现信息共享与决策协同。在工程实践中,多智能体框架的价值在于提升任务处理效率、增强系统鲁棒性,并支持模块化开发。典型的应用场景包括自动化工作流编排、复杂问题求解以及人机协同交互。本文以OpenAI Agents SDK为例,深入探讨如何利用其提供的智能体(Agent)、会话(Ses

weixin_28725959的博客 603

快衰落、慢衰落,平坦衰落、频率选择性衰落

目录一、大尺度衰落和小尺度衰落二、平坦衰落和频率选择性衰落1.反射墙、固定天线模型2.相干带宽和时延扩展三、快衰落和慢衰落1.反射墙、运动天线模型2.相干时间和多普勒扩展四、联系总结 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、大尺度衰落和小尺度衰落 移动无线信道的主要特征是信道强度关于时间和频率的变化,大致分两种: 大尺度衰落: .

weixin_45662974的博客 3万+

C++标准库中的复数类

// #include "complex.h" #include <windows.h> #include <iostream> #include <complex> using namespace std; int main() { complex<double> com1(1,2); complex<double> com2(3,4); complex<double> com3; //用于加法

李昊的博客 439

智慧加油站小程序数据库设计文档

【代码】智慧加油站小程序数据库设计文档。

低代码布道师的博客 1402

C++面向对象编程核心:从类设计到内存管理与多态机制

面向对象编程(OOP)是一种通过类和对象来模拟现实世界的编程范式,其核心在于封装、继承和多态三大特性。在C++中,OOP的实现紧密关联于内存管理机制,特别是对于带指针的类,需要手动实现深拷贝来管理动态分配的资源,避免内存泄漏和浅拷贝问题。理解栈与堆的区别、对象的生命周期以及虚函数表(vptr/vtbl)的工作原理,对于编写高效、安全的C++代码至关重要。这些技术广泛应用于游戏引擎、高性能计算和系统软件开发中,是掌握C++面向对象编程的基础。本文基于侯捷老师的课程,重点解析了类设计、内存管理和多态机制等核心概

weixin_30321709的博客 526

AD9613操作控制

输出250M时钟给AD9613,过FPGA ILA逻辑分析仪将AD9613采集的两个通道ADC数据250M数据显示出来。其中AD9613输出的是LVDS数据,通过select IO核转为并行数据。 一,搜索IP核:selectIO interface wizad ,并双击配置 配置为input,DDR模式,数据位宽为12bit,IO类型为差分,这里配置的是12对数据差分对。然后配置外部差分时钟。 将tap setting 设置为13,将时钟的边沿对准数据的中间,以免数据出错 二,

wangjie36的博客 4047

【XSRP软件无线电】基于软件无线电平台的QPSK频带通信系统设计(含有完整工程资料获取链接)

软件无线电(Software Defined Radio, SDR)是一种无线通信系统,它通过软件来定义和实现无线电的功能,而不是依赖于传统的硬件电路。SDR平台的核心思想是将传统无线电系统中的大部分硬件功能,如调制解调、信号处理、频率选择等,通过软件来实现。这种设计理念使得SDR具有高度的灵活性和可重配置性,能够适应不同的通信标准和频段,快速适应新的通信技术。

嵌入式技术开发 3280

C++标准库提供的complex定义的复数对象学习笔记

complex类可以定义多种数据类型的复数,其实部和虚部的数据类型可以是整数也可以是实数,即complex类是一个模板类,定义复数对象时,才指明数据成员类型,格式为: complex 对象名称(实部值,虚部值); #include #include #include /* run this program using the console pauser or add your o

宇宙精英 2万+

B3640 T3 句子反转

要求将这些单词倒序输出。而且对于每个单词,如果是小写词,应当转为大写;如果是大写词,应当转为小写;如果是自然数,应该倒转输出。给定一行句子,每个词之间用空格隔开,要么是全小写英文单词,要么是全大写英文单词,要么是自然数。第一次做的时候0分,两个小时没做出来。仅一行,表示程序对句子的处理结果。仅一行,即需要反转的句子。

小前日记 366

[C++杂记] int转string

int转string 现列出3中方法,各有优劣。 1、多位整数转化为string 下面的代码片段展示的是正整数转化为string: int low; string answer; while(n>0){ low = n % 10; n = n / 10; answer += low + '0'; } char temp; for(int i = 0; i < answer.leng

yishaxiaoyao的专栏 703

Python中的字典(Dictionary)学习

上一章节,我们学习了列表(List) 和 元组(tuple) 来表示有序集合。而我们在讲列表(list)的时候,我们用了列表(list) 来存储用户的姓名。那么如果我们为了方便联系这些童鞋,要把电话号码也添加进去,该怎么做呢?但是这样很不方便,我们把电话号码记录下来,就是为了有什么事能及时联系上这些童鞋。如果用列表来存储这些,列表越长,我们查找起来耗时就越长。

热情、奔放、快乐编程! 502

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C语言常用库函数实现(一)_内存拷贝

库函数的实现也是面试中的常考题,因为这是最能体现C语言功底的。 一、strcpy与strncpy 先看一下函数的原型: strcpy函数可以按如下的方式实现: 点击(此处)折叠或打开 char*strcpy(char*strDest,constchar*strSrc) { if(strDest==NULL) ||...

EmbeddedCoder 的优快云博客 3637

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++(10)——实现复数类和String类

复数类 class CComplex { public: CComplex(int r = 0, int z = 0) :a(r),b(z) { } ~CComplex() { } CComplex operator+(const CComplex &com) { return CComplex(this->a + com.a,this->b + com.b); } void show() { cout << "实部:" <&lt

青布衫白少年的博客 434

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C/C++库函数的string内存拷贝

面试过程中,面试官一般会让写一些基础的库函数,比如strcpy,memcpy,memmove等。下面做个解释函数。 1、标准库函数strcpy,把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。 char *strcpy(char *dst,const char *src) { assert(dst != NULL); assert(src !=

u011283922的博客 1117

c/c++ 标准库函数实现 ------strcpy

如有错误,欢迎指正 #include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;stdlib.h&gt; //先把大家都能考虑到的实现写一下吧 char* strcpy1(char* dest,char* origin) { if(dest==NULL ||origin==NULL)                ...

qq_27563511的博客 971

【C++对象和类】复数类

仅作为自己的学习记录,欢迎指正和建议 2. Description 定义一个复数类complex,数据成员包括实部real和虚部imag,均为double类型。成员函数包括: (1) 默认构造函数(即无参的构造函数),实部和虚部分别赋值为1.0,1.0 ; (2) 带两个参数的构造函数; (3) 输出复数的函数display, 输出格式为 实部+虚部i,例如: 1.00+1.00i ; (4) ...

weixin_43773009的博客 3596

C++:数值类型转string

#include<iostream> #include<string> #include <sstream> using namespace std; //@ 函数模板 //@ 将一些数值转换为string类型 template <typename T> string Convert(T input) { stringstream ss; ss << input; string str(ss.str()); return str; } .

己亥谷雨 850

C++复习之实现标准库的字符串操作函数

C++复习之实现标准库的字符串操作函数strcpy 、 strncpy 、 memmove 、 memcpy 、 memset 、 strlen 、 strncat 、 strcmp 、 strncmp 、 strstr 、 strchr 的实现

MasonChen的专栏 474

使用复数运算库

使用复数运算库 复数是由实部和虚部组成的数。例如: 3.2 + 4i 1 + 3i 1 + 2.3i 在特例情况下,如 0 + 3i 是纯虚数,通常写为 3i;5 + 0i 是纯实数,通常写为 5。可以使用 complex 数据类型来表示复数。 注 – 复数运算库 (libcomplex) 仅可用于兼容模式 ( -compat[ =4]) 下。在标准模式(缺省模式)下,C++

wanglp094的专栏 4742

c++标准异常库,字符串拷贝

标准库中提供了很多异常类,他们通过类继承组织起来 // c++标准异常.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<stdexcept> using namespace std; class Person { public: int age; Person() ...

庸人自扰 199
上一篇: 【高质量C++/C总结11】C++线程的基本使用方式
下一篇: 【算法】ACO蚂蚁寻路最短路径TSP问题-多篇文章总结
尹豆(douysu)
博客等级 码龄9年 151粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值