C++ 使用动态内存创建一个类

这篇具有很好参考价值的文章主要介绍了C++ 使用动态内存创建一个类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用动态内存的一个常见原因是允许多个对象共享相同的状态。

例如,假定我们希望定义一个名为Blob 的类,保存一组元素。与容器不同,我们希望Blob对象的不同拷贝之间共享相同的元素。即,当我们拷贝一个Blob时,原Blob对象及其拷贝应该引用相同的底层元素。现在我们先定义一个管理string的类,此版本命名为StrBlob

定义 StrBlob类

实现一个新的集合类型的最简单方法是使用某个标准库容器来管理元素。采用这种方法,我们可以借助标准库类型来管理元素所使用的内存空间。在本例中,我们将使用vector来保存元素。

但是,我们不能在一个Blob对象内直接保存vector,因为一个对象的成员在对象销毁时也会被销毁。例如,

  • 假定b1 b2是两个Blob对象,共享相同的vector
  • 如果此vector保存在其中一个Blob中——例如b2中,那么当b2离开作用域时,此vector也将被销毁,也就是说其中的元素都将不复存在。为了保证 vector中的元素继续存在,我们将vector保存在动态内存中。

为了实现我们所希望的数据共享,我们为每个StrBlob设置一个shared_ptr来管理动态分配的 vector。此 shared_ptr的成员将记录有多少个StrBlob 共享相同的vector,并在vector的最后一个使用者被销毁时释放vector

我们还需要确定这个类应该提供什么操作。当前,我们将实现一个vector操作的小的子集。我们会修改访问元素的操作(如 frontback): 在我们的类中,如果用户试图访问不存在的元素,这些操作会抛出一个异常。

我们的类有一个默认构造函数和一个构造函数,接受单一的 initializer_list<string>类型参数。此构造函数可以接受一个初始化器的花括号列表

initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。在进行函数调用的时候需要使用花括号将所有的参数括起来。

class StrBlob{
public:
	typedef std::vector<std::string>::size_type size_type;
	
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	//添加和删除元素
	void push_back(const std::string &t){ data->push_back(t); }
	void pop_back();
	
	//元素访问
	std::string& front();
	std::string& back();
	
private:
	std::shared_ptr<std::vector<std::string>> data;
	//如果data[i]不合法,抛出一个异常
	void check(size_type i, const std::string &msg) const;
};

在此类中,我们实现了sizeemptypush_back成员。这些成员通过指向底层vectordata成员来完成它们的工作。例如,对一个 StrBlob对象调用size()会调用data->size(),依此类推。

StrBlob构造函数

两个构造函数都使用初始化列表来初始化其data成员,令它指向一个动态分配的vector。默认构造函数分配一个空vector:

StrBlob::StrBlob() : data(make_shared<vector<string>>()){ }
StrBlob::StrBlob(initializer_list<string> il): data(make_shared<vector<string>>(il)) { }

接受一个initializer_list的构造函数将其参数传递给对应的vector构造函数。此构造函数通过拷贝列表中的值来初始化vector的元素。

元素访问成员函数

pop_backfrontback操作访问vector中的元素。这些操作在试图访问元素之前必须检查元素是否存在。由于这些成员函数需要做相同的检查操作,我们为StrBlob定义了一个名为checkprivate工具函数,它检查一个给定索引是否在合法范围内。除了索引,check还接受一个string参数,它会将此参数传递给异常处理程序,这个string描述了错误内容:

void StrBlob::check(size_type i, const string &msg) const
{
	if(i >= data->size())
		throw out_of_range(msg);
}

pop_back元素访问成员函数首先调用check。如果check成功,这些成员函数继续利用底层vector的操作来完成自己的工作:

string& StrBlob::front()
{
	//如果vector为空,check会抛出一个异常
	check(0, "front on empty StrBlob");
	return data->front();
}
string& StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
void StrBlob::pop_back()
{
	check(0, "pop_back on empty StrBlob");
	data->pop_back();
}

StrBlob 的拷贝、赋值和销毁

StrBlob使用默认版本的拷贝、赋值和销毁成员函数来对此类型的对象进行这些操作。默认情况下,这些操作拷贝、赋值和销毁类的数据成员。
我们的StrBlob类只有一个数据成员,它是shared_ptr类型。因此,当我们拷贝、赋值或销毁一个 StrBlob对象时,它的shared_ptr成员会被拷贝、赋值或销毁。

  • 拷贝一个shared_ptr会递增其引用计数;
  • 将一个shared_ptr赋予另一个shared_ptr会递增赋值号右侧shared_ptr的引用计数,而递减左侧shared_ptr的引用计数。
  • 如果一个shared_ptr的引用计数变为0,它所指向的对象会被自动销毁。因此,对于由 StrBlob构造函数分配的vector,当最后一个指向它的StrBlob对象被销毁时,它会随之被自动销毁。

注:仅供学习参考,如有不足,欢迎指正!文章来源地址https://www.toymoban.com/news/detail-427999.html

到了这里,关于C++ 使用动态内存创建一个类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】动态内存管理

      说明: 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的; 2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口     创建共享共享内存,做进程间通信; 3. 堆用于程序运行时动态内存分配,堆是可以上增长的;

    2024年02月06日
    浏览(41)
  • 【C++】——动态内存管理

      目录 🌞导读 🌔C/C++内存分布  🌔C++内存管理方式  🌗new/delete操作内置类型  🌗new和delete的使用方法 🌔operator new与operator delete函数 🌔new和delete的实现原理 🌗内置类型 🌗自定义类型 🌔定位new表达式  🌗使用格式 🌔malloc/free和new/delete的区别 🌟作者简介: 日出等日

    2024年02月07日
    浏览(35)
  • C++ 动态内存

    了解动态内存在 C++ 中是如何工作的是成为一名合格的 C++ 程序员必不可少的。C++ 程序中的内存分为两个部分: 栈: 在函数内部声明的所有变量都将占用栈内存。 堆: 这是程序中未使用的内存,在程序运行时可用于动态分配内存。 很多时候,您无法提前预知需要多少内存来

    2024年02月11日
    浏览(33)
  • C++类和动态内存分配

    C++能够在程序运行时决定内存的分配,而不是只在编译阶段,因此,就可以根据程序的需要,而不是根据一系列严格的存储类型规则来使用内存,C++使用new和delete运算符来动态控制内存,但是,在类中使用这些运算符会导致许多新的问题,在这种情况下,析构函数就是必不可

    2024年04月16日
    浏览(43)
  • C++中内存的动态管理

    我们在C语言中了解到可以在栈区动态开辟空间,并且用完要进行释放,防止内存泄漏。 C++中也有可以进行动态开辟空间和释放空间的操作符 new  、 delete, 虽然C++中也可以用malloc、calloc、realloc、free函数,但是C++中引入了类,而类中又有构造函数和析构函数,在实例化对象时

    2024年02月14日
    浏览(40)
  • C++ 指针进阶:动态分配内存

    malloc 是 stdlib.h 库中的函数,原型为 void *__cdecl malloc(size_t _Size); : 作用 : malloc 函数沿空闲链表(位于内存 堆空间 中)申请一块满足需求的内存块,将所需大小的内存块分配给用户剩下的返回到链表上; 并返回指向该内存区的首地址的指针,意该指针的类型为 void * ,因此

    2024年02月05日
    浏览(46)
  • C语言---认识动态内存管理并实现一个动态通讯录:静态通讯录别来沾边

    👧个人主页:@小沈熬夜秃头中୧⍤⃝❅ 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C语言学习 🔑本章内容:动态内存管理 送给各位💌:当你的能力还驾驭不了你的目标时那你就应该沉下心来历练 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇

    2024年02月08日
    浏览(92)
  • C++ 引用和指针:内存地址、创建方法及应用解析

    引用变量是对现有变量的“别名”,它是使用 运算符创建的: 现在,我们可以使用变量名 food 或引用名 meal 来引用食物变量: 内存地址 在前一页的示例中,使用 运算符创建了一个引用变量。但它也可以用于获取变量的内存地址;即变量在计算机上存储的位置。 当在 C++ 中

    2024年04月11日
    浏览(35)
  • C++内存泄露排查的一个案例

    背景: 这熟悉的线条. 请求量没啥波动, 不用怀疑, 就是内存泄露了. 方案一 Valgrind Valgrind可以用来检测是否有非法使用内存的问题, 如: 访问未初始化的内存,访问数组越界, 忘记释放动态内存的问题; 首先需要定位是哪个进程的内存泄露. 使用top命令, 然后shift+m按照内存排序, 找

    2024年02月13日
    浏览(38)
  • C++动态内存开辟与释放new和delete

    🐶博主主页: @ᰔᩚ. 一怀明月ꦿ  ❤️‍🔥 专栏系列: 线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,数据结构 🔥 座右铭: “不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

    2024年02月03日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包