对象应用:C++字符串和vector,对象的new与delete重构

news2024/12/29 10:19:49

对象应用

  • C++字符串和vector
    • 字符串创建方式
    • 字符串拼接
      • 字符串追加
    • 字符串截断
    • auto
    • vector创建方式
    • vector操作
  • new与delete重构
    • new与delete的工作步骤
    • new与delete重构应用
      • 只能生成栈对象
      • 只能生成堆对象

C++字符串和vector

C++的字符串是一个对象,存在于std标准库中,是std标准库提供的自定义类类型
所占存储空间较大,40字节,数据成员一般都包含
在这里插入图片描述
vector是一种动态数组,也存在与std标准库中,一般都有size和capacity两个数据成员

字符串创建方式

默认创建

string s1;

C语言字符串创建

string s2("Hello");

指定长度的单个字符创建

string s3(10,'a');

字符串拼接

只能用+拼接,+两边必须有一个是string类对象

	string s4 = s3 + s2;
	s4 = s3 + "Hello";
	s4 = "Hello" + s3;

字符串追加

追加特定长度字符

s3.append(3,'a');

追加字符串

s3.append("Hello");

追加string类对象

s3.append(s2);

追加string类对象指定起始位置指定长度

s3.apend(s2,0,5);

字符串截断

//参数1,pos,指定起始位置,参数2,len,指定长度

cout<<s3.substr(0,3)<<endl;

auto

C++的一种自动遍历模式,auto是自动推导,如果不带引用可能会浪费空间

for(auto& t: s3)
{
	cout<<t<<' ';
}

完整代码

#include <iostream>

using std::cout;
using std::endl;
using std::string;
//std::string 标准库提供的自定义类类型

void sp(string& s)
{
	cout << "s:" << s << endl;
	cout << "s:sizeof:" << sizeof(s) << endl;
	cout << "s.size:" << s.size() << endl;
	cout << "s.length:" << s.length() << endl;

	cout << endl;
}
int main()
{
	//三种构造函数
	string s1;
	string s2("Hello");//c -to c++
	string s3(10, 'a');

	sp(s1);
	sp(s2);
	sp(s3);

	//字符串拼接
	string s4 = s3 + s2;
	s4 = s3 + "Hello";
	s4 = "Hello" + s3;
	sp(s4);
	//操作运算符两边必须有一个是string对象

	//追加	
	s3.append(3, 'a');//追加字符
	sp(s3);
	s3.append("Hello");//追加字符串
	s3.append(s2);//追加string对象
	s3.append(s2,0,5);//追加特定起始位置特定长度的string对象
	sp(s3);

	//截断
	cout << s3.substr(0, 3) << endl;//参数一pos,参数2len

	cout << &s1 << endl;//对对象取地址,得到是对象首地址,而不是字符串内容首地址

	cout << endl;

	//auto是自动推导,&是引用,没有引用会浪费内存
	for (auto& t : s3)
	{
		cout << t << ' ';
	}
	return 0;
}

vector创建方式

默认创建

vector<int> numbers;

初始化创建

vector<int> numbers(10,0);//创建大小为10的数组,数组元素皆为0,vector容量为10

vector操作

添加元素

numbers.push_back(1);

删除末尾元素

numbers.pop_back();

代码实现

#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

void vp(vector<int>& numbers)
{
	cout << "numbers:size:" << numbers.size() << endl;
	cout << "numbers.capacity:" << numbers.capacity() << endl;

}
int main()
{
	vector<int> numbers;
	vp(numbers);

	for (int i = 0; i < 10; ++i)
	{
		numbers.push_back(i);
		vp(numbers);
	}

	//初始化操作
	vector<int> a(11, 0);
	for (auto& t : a) cout << t << ' ';

	vp(a);

	return 0;
}

有一个需要我们值得注意的地方
vector对象在size为capacity时且还需要再添加新的元素时,会进行扩容

扩容步骤
申请一个原先x倍的空间
将旧空间的元素拷贝到新空间中
销毁旧空间,vector数组指向新空间

不同编译器在扩容时的倍率不同
在这里插入图片描述
在这里插入图片描述
可以看到,一般的编译器扩容一般都是2倍扩容,而vs会以原来的1.5倍扩容

new与delete重构

new与delete的工作步骤

new:

1.调用operator new标准库函数申请未定义的空间
2.在该空间调用构造函数初始化对象
3.返回一个相应类型的指针
形式 void* operator new(size_t)

delete

调用析构函数
调用operator delete标准库函数回收对象空间

代码实现

#include <iostream>
#include <cstdlib>
#include <cstring>

using std::cout;
using std::endl;

class Student
{
public:
	Student(const char* name,const int& id)
	:_name(new char[strlen(name) + 1]())
	,_id(id)
	{
		strcpy(_name,name);
		cout<<"Have done create"<<endl;
	}

	void release()
	{
		delete[] _name;
		_name = nullptr;
	}
	~Student()
	{
		if(_name) release();
		cout<<"~Student"<<endl;
	}
	
	void print() const
	{
		cout << "name:" << _name << endl;
		cout << "id:" << _id << endl;
	}
	
	void* operator new(size_t sz)
	{
		cout<<"Operator new"<<endl;
		return malloc(sz);
	}
	void operator delete(void* p)
	{
		cout<<"Operator delete"<<endl;
		free(p);
	}
private:
	char* _name;
	int _id;
}
int main()
{
	return 0;
}

size_t 类型无需担心会不会申请出错

new与delete重构应用

生成栈对象的条件

1.需要合法的构造函数
2.需要合法的析构函数

生成堆对象的条件

1.需要合法的operator new库函数
2.需要合法的构造函数

只能生成栈对象

方法:将 operator new库函数私有化

#include <iostream>
#include <cstdlib>
#include <cstring>

using std::cout;
using std::endl;

class Student
{
public:
	Student(const char* name,const int& id)
	:_name(new char[strlen(name) + 1]())
	,_id(id)
	{
		strcpy(_name,name);
		cout<<"Have done create"<<endl;
	}

	void release()
	{
		delete[] _name;
		_name = nullptr;
	}
	~Student()
	{
		if(_name) release();
		cout<<"~Student"<<endl;
	}
	
	void print() const
	{
		cout << "name:" << _name << endl;
		cout << "id:" << _id << endl;
	}
private:
	char* _name;
	int _id;
	void* operator new(size_t sz){}//因为不需要创建堆对象,所以去重构的过程没有意义,只需要在private内声明即可
	void operator delete(void* p){}
};

void test1()
{
	Student s1("Rose",100);
	s1.print();
}
int main()
{
	test1();
	return 0;
}

打印结果

Have done create
name:Rose
id:100
~Student

只能生成堆对象

方法:将析构函数私有化

#include <iostream>
#include <cstdlib>
#include <cstring>

using std::cout;
using std::endl;

class Student
{
public:
	Student(const char* name,const int& id)
	:_name(new char[strlen(name) + 1]())
	,_id(id)
	{
		strcpy(_name,name);
		cout<<"Have done create"<<endl;
	}

	void release()
	{
		delete[] _name;
		_name = nullptr;
	}

	
	void print() const
	{
		cout << "name:" << _name << endl;
		cout << "id:" << _id << endl;
	}
	void* operator new(size_t sz)
	{
		malloc(sz);
		cout<<"Operator new"<<endl;
	}
	void operator delete(void *p)
	{
		delete p;
		cout<<"Operator delete"<<endl;
	}
private:
	char* _name;
	int _id;
		~Student()
	{
		if(_name) release();
		cout<<"~Student"<<endl;
	}
};

void test2()
{
	Student* sp1 = new Student("Jackie",101);
	sp1->print();
	sp1->delete;
}
int main()
{
	test2();
	return 0;
}

此时我们运行发现,在sp1->delete行出错,由此我们知道delete在销毁对象时调用了析构函数,而析构函数因为他的私有化而不可用,因此需要在public里新建一个函数用来替换delete操作

void destroy()
{
	this->~Student();
}

此时我们在内存检测时发现,对象本身没有被真正销毁,因此在destroy内部调用析构函数是错误的,应该直接进行delete操作,由于是在类的内部进行delete,可以访问析构函数,所以其操作是完全可行的

void destroy()
{
	delete this;
}

代码实现

#include <iostream>
#include <cstring>

using std::cout;
using std::endl;

//new 和 delete 都是用operator的标准库函数

class Student {
public:

	Student(const char* name, const int& id)
		:_name(new char[strlen(name) + 1]())
		, _id(id)
	{
		strcpy(_name, name);
		cout << "Have done create!" << endl;
	}
	void release()
	{
		delete[] _name;
		_name = nullptr;
	}

	void destroy()
	{
		//直接调用析构函数不能销毁对象
		//this->~Student();
		delete this;
	}

	void print() const
	{
		cout << "name:" << _name << endl;
		cout << "id:" << _id << endl;
	}
	//这里的new和delete只针对该类的创建销毁,放在全局定义时则会变成对全部的new和delete重构
	void* operator new(size_t sz)//不创建就会系统默认提供
	{
		cout << "Operator new" << endl;
		return malloc(sz);
	}
	void operator delete(void* p)
	{
		cout << "Operator delete" << endl;
		free(p);
	}
private:
	char* _name;
	int _id;

	~Student()
	{
		if (_name) release();

		cout << "Have done delete" << endl;
	}
};
void test2()
{
	//创建堆对象的条件
	//需要合法的operator new库函数
	//需要合法的构造函数
	Student* sp1 = new Student("Jackie", 100);
	sp1->print();
	sp1->destroy();	
	//delete sp1; 因为私有化,delete不可用,需要优化

	//如何让一个类只能生成栈对象,不能生成堆对象
	//解决方案
	//将operator new库函数私有化
}
int main()
{
	//new的工作步骤
	//调用operator new标准库函数申请未定义类型的空间
	//在该空间调用构造函数初始化对象
	//返回一个相应类型的指针
	//形式:void* operator new(size_t)


	//delete工作步骤
	//调用析构函数
	//调用operator delete标准库函数回收对象空间


	test2();

	return 0;
}

打印结果

Operator new
Have done create!
name:Jackie
id:100
Have done delete
Operator delete

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

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

相关文章

Python基础入门(4)—— 什么是偷懒编程法?是类、对象和继承

文章目录 00 | &#x1f603;为什么学习类&#xff1f;&#x1f603;01 | &#x1f604;创建类&#x1f604;02 | &#x1f606;创建对象&#x1f606;03 | &#x1f609;访问对象属性和方法&#x1f609;04 | &#x1f60a;构造函数&#x1f60a;05 | &#x1f60b;继承&#…

Shell编程之数组

目录 一、数组的基本概念 二、定义数组的方法 方法一&#xff1a; ​编辑 方法二&#xff1a; 方法三&#xff1a; ​编辑 方法四&#xff1a; 三、 数组的输出&#xff0c;删除和长度统计 1&#xff09;数组元素的输出 2&#xff09;数组全部元素输出 3&#xff0…

一种用于提高无线传感器网络寿命的改进LEACH协议(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 无线传感器网络具有网络灵活性强、网络规模可变等优点&#xff0c;广泛应用于军事、工业等领域。无线传感器网络的基本网络路由…

Mybatis一级缓存详解

目录 一级缓存 一级缓存的组织 一级缓存的生命周期 一级缓存的工作流程 Cache接口的设计以及CacheKey的定义 一级缓存的性能分析 一级缓存与Spring 事务一级缓存存在的弊端 官方文档分析 Spring通过Mybatis调用数据库的过程 一级缓存 对于会话&#xff08;Session&am…

Nacos-01-Nacos基本介绍

背景 ​ 服务发现是⼀个古老的话题&#xff0c;当应用开始脱离单机运行和访问时&#xff0c;服务发现就诞生了。目前的网络架构是每个主机都有⼀个独立的 IP 地址&#xff0c;那么服务发现基本上都是通过某种方式获取到服务所部署的 IP 地址。DNS 协议是最早将⼀个网络名称翻译…

让AI帮忙写个需求,AI写出来了,只是有bug而已

需求 使用原生JS和iframe&#xff0c;嵌入网页进行轮播&#xff0c;需要可以点击暂停、上一页、下一页。 AI的答案 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>轮播图</title><style>* {margin: 0;padd…

看板项目管理:如何可视化工作以提高生产力?

如果你一直关心优化工作流程&#xff0c;提高你或团队的生产力&#xff0c;你肯定听说过看板这个词。 看板是一种工作管理方法&#xff0c;可以将整个工作流程以及构成工作流程的每个单独活动可视化&#xff0c;从而可以识别瓶颈和优化整体流程。 在这方面&#xff0c;看板的…

Python基础(二)

目录 一、类型转换 1、为什么需要数据类型转换 2、数据类型转化的函数 3、str()函数类型转换使用 4、int()函数类型转换使用 4.1int()不能将str类型数据转换成int 4.2int()将bool类型转换成int 4.3int()将float转换成int 5、Float()函数类型转换使用 5.1Float()函数不…

ros imu可视化(ubantu)

可以用下面的链接安装ros 安装ros 在home下建立workspace&#xff0c;添加环境变量 export $ROS_PACKAGE_PATHROS_PACKAGE_PATH:/home/workspace在workspace下建立src文件夹&#xff0c;将fdilink_ahrs_ROS1解压在src目录下面 在workspace下运行以下命令&#xff1a; catkin_…

【牛客面试必刷TOP101】有效括号序列、滑动窗口的最大值

BM44 有效括号序列 点击进入该题 描述&#xff1a; 给出一个仅包含字符’(‘,’)‘,’{‘,’}‘,’[‘和’],的字符串&#xff0c;判断给出的字符串是否是合法的括号序列。 括号必须以正确的顺序关闭&#xff0c;"()“和”()[]{}“都是合法的括号序列&#xff0c;但”(]“…

(七)如何实现即时通信系统中用户的文字聊天功能?

文章目录 一、引言二、实现用户文字功能2.1 使用QTextEdit控件实现用户输入文字消息2.2 实现文字消息的发送和接收2.3 实现文字消息的展示和管理 三、解码接收到的文字消息3.1 接收数据并解码3.2 在客户端展示文字消息3.3 客户端关键代码展示3.4 服务端关键代码展示 四、效果展…

干货 | 如何做一个简单的访谈研究?

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 心理学中研究中&#xff0c;大家常用的研究方法大多是实验法、问卷调查法等&#xff0c;这些均是定量研究。 其实&#xff0c;作为质性研究中常用的访谈法&#xff0c;可对个体的内心想法进…

【操作系统】从操作系统底层出发,成为更好的程序员

冯老爷子的模型 首先&#xff0c;我们从一个问题开始(&#xffe3;∇&#xffe3;)/ 为什么需要程序员&#xff1f; 早期的计算机程序是硬件化的&#xff0c;即使用各种门电路组装出一个固定的电路板&#xff0c;这个电路板只能用于执行某个特定的程序&#xff0c;如果需要修…

学生电费管理系统

随着现代化的发展和科技的进步&#xff0c;各种智能化的系统应运而生。其中&#xff0c;学生电费管理系统是一个非常实用的系统&#xff0c;它可以帮助学校管理电费&#xff0c;提高学生的电费管理意识&#xff0c;减少学校的电费支出。本文将着重介绍该系统的作用、特点以及优…

【hive】基于Qt5和libuv udp 的lan chat

作者已经不更新了,但是很棒 在线用户列表: 聊天窗口 主程序 单独的网络线程: network_thread data管理关联网络管理的 程序update升级更新 和消息收到 即可

【Java】面试常问知识点(数据库相关知识)

Redis Redis数据结构&#xff0c;跳表如何实现&#xff1f;跳表添加层级的时机&#xff1f; 布隆过滤器的底层原理 Redis数据结构 有5中数据结构&#xff0c;string&#xff08;字符串类型&#xff09;、list&#xff08;列表类型&#xff09;、hash&#xff08;哈希表类型…

Ubuntu 20.04 系统配置 OpenVINO 2022.3 环境

由于 OpenVINO 2021 版本在调用 IECore 时会出现 Segmentation fault 的问题&#xff0c;因此需要将其升级为 2022 版本的。 1. 卸载原来版本的 OpenVINO 进入OpenVINO的卸载目录&#xff0c;通常在 /opt/intel 文件夹下&#xff0c; cd /opt/intel/openvino_2021/openvino_…

SOA协议DDS和Some/IP对比

SOME/IP 和 DDS 均已被纳入AUTOSAR AP的平台标准中。 SOME/IP 和 DDS是在不同的应用场景和不同的需求下诞生的技术&#xff0c;所以它们之间注定有很大的区别。 SOME/IP SOME/IP的全称为&#xff1a;Scalable service-Oriented MiddlewarE over IP&#xff0c;是一种面向服务…

Codeforces Round 871 (Div. 4)【A、B、C、D、E、F、G、H】

文章目录 A. Love Story(模拟)B. Blank Space(模拟)C. Mr. Perfectly Fine&#xff08;模拟&#xff09;D. Gold Rush(小思维)E. The Lakes(DFS)F. Forever Winter(简单的图)G. Hits Different&#xff08;二维前缀和&#xff09;H. Dont Blame Me(状态压缩dp) 传送门 A. Love …

视频文本检索之CLIP4Clip

论文&#xff1a;CLIP4Clip: An Empirical Study of CLIP for End to End Video Clip Retrieval GitHub&#xff1a;https://github.com/ArrowLuo/CLIP4Clip 论文基于图片-文本检索模型CLIP (Contrastive Language-Image Pretraining)提出了视频-文本检索模型CLIP4Clip (CLIP …