ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

动态内存

2022-03-20 08:34:40  阅读:151  来源: 互联网

标签:string int 动态内存 new shared unique ptr


#include<iostream>
#include<string>
#include<vector>
#include<numeric>
#include<list>
#include<functional>
using namespace std;
/*
到目前为止,我们使用的对象都有严格的生存期,全局对象在程序启动时分配,在程序结束时销毁
对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时 被销毁,局部static
对象在第一次使用前分配,在程序结束时销毁
*/
//静态内存用来保存局部static对象,类static数据成员,以及定义在任何函数之外的变量
//栈内存用来保存定义在函数内的非static对象
//内存池,部分内存被称作自由空间或堆,程序用堆来存储动态分配的对象

//shared_ptr:允许多个指针指向同一个对象
void test01() {
	shared_ptr<string>p1; //可以指向string
	shared_ptr<list<int>>p2; //可以指向int的list
	//默认初始化的智能指针保存着一个空指针,对智能指针解引用可以返回它指向的对象
	if (p1 && p1->empty())
		*p1 = "h1";

	//make_shared函数(定义在memory中)
	shared_ptr<int>p3 = make_shared<int>(42);
	shared_ptr<string>p4 = make_shared<string>(10, 'a');
	shared_ptr<int>p5 = make_shared<int>(); 
	//p6指向一个动态分配的空vector<string>
	auto p6 = make_shared<vector<string>>();

	//shared_ptr的拷贝和赋值
	//当进行拷贝和赋值时,每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象
	auto p = make_shared < int>(42); //p指向的对象只有p一个引用者
	auto q(p); //p和q指向相同的对象,此对象有两个引用者


	//每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论何时我们拷贝一个shared_ptr时,计数器都会递增
	//当我们给shared_ptr赋予一个新的值或者是shared_ptr被销毁时,计数器就会递减
	auto r = make_shared<int>(42);
	r = q; //给r赋值,递增q指向对象的引用计数,递减r原来指向对象的引用计数

	//shared_ptr自动销毁所管理的对象-析构函数
	/*
	shared_ptr的析构函数会递减它所指向对象的引用计数,如果引用计数变成0,shared_ptr的析构函数就会销毁对象,并释放它所占的内存
	*/

	/*
	1.对于一块内存,shared_ptr类保证只要有任何shared_ptr对象引用它,它就不会被释放掉
	2.如果你将shared_ptr存放于一个容器中,而后不再需要全部元素,而只是用其中的一部分,
	要记得用erase删除不再需要的那些元素
	*/
}

/*
使用了动态生存期的资源的类
程序使用动态内存处于下面三种原因
1.程序不知道自己需要使用多少对象
2.程序不知道所需的对象的准确类型
3.程序需要在多个对象间共享数据
*/
void test07() {
	/*
	我们拷贝一个vector时,原vector和副本vector中的元素是相互分离的
	由一个vector分配的元素只有当这个vector存在时才存在,当一个vector被销毁时
	这个vector中的元素也都被销毁
	*/
	vector<string>v1;
	{
		vector<string>v2 = { "a", "an", "the" };
		v1 = v2; //从v2拷贝元素到v1中
	}
	//v2被销毁,其中的元素也被销毁,v三个元素是原来v2中元素的拷贝

	/*
	一般而言,如果两个对象共享底层的数据,当某个对象被销毁时,我们不能单方面的销毁底层数据
	*/
	//blog对象是一不同拷贝之间共享相同的元素的一个类
	//Blob<string> b1;
	//{
	//	Blob<string>b2 = { "a", "an", "the" };
	//	b1 = b2; // b1和b2共享相同的元素
	//}//b2被销毁了,但是b2中的元素不能被销毁
}

//数据共享类
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;
	void check(size_type i, const std::string& msg) const;
};

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

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

string& StrBlob::back() {
	check(0, "back on empty StrBlob");
}

void StrBlob::pop_back() {
	check(0, "pop_back on empty StrBlob");
}


//直接管理内存
void test02() {
	int* p1 = new int;
	string* ps = new string; //ps指向为初始化的int
	int* p1 = new int(1024);
	string* ps = new string(10, '9');
	vector<int>* pv = new vector<int>{ 0, 1, 2, 3 };

	//使用auto时,由于编译器要使用初始化器的类型类推断我们要分配的类型,只有当括号中仅有单一初始器时才可以使用auto
	auto p1 = new auto(10);
	//auto p2 = new auto{a, b, c}; 错误,括号中只能有单个初始化器

	//动态分配的const对象
	const int* pci = new const int(1024);
	const string* pvs = new const string;
	/*
	类似于其他任何const对象,一个动态分配的const对象必须进行初始化,对于一个定义了默认构造函数的类类型,
	其const动态对象可以是隐式初始化,而其他类型的对象就必须显示初始化,由于分配的对象是const,new返回的指针是一个指向const的
	指针
	*/
	
	//内存耗尽
	int* p1 = new int; //如果分配失败,new抛出std::bad_alloc
	int* p2 = new (nothrow)int; //如果分配失败,new返回一个空指针

	//指针和delete
	/*
	1.忘记delete内存
	2.使用已经释放掉的对象
	3.同一块内存释放两次
	delete一个指针后,该指针就变成无效了,为空悬指针
	*/
	
	int* p(new int(42));
	auto q = p;
	delete p; //p和q都变成无效的
	p = nullptr;

	//share_ptr和new结合使用
	shared_ptr<double>p1;
	shared_ptr<int>p2(new int(42));
	//shared_ptr<int>p1 = new int(1024); 错误必须使用直接初始化
	/*shared_ptr<int> clone(int p) {
		return new int(p); //错误,隐式转换为shared_ptr<int>
	}*/
	
	//不要混合使用普通指针和智能指针
	int* x(new int(1024)); //危险,x是一个普通指针,不是一个智能指针
	//也不要使用get初始化另一个智能指针或为智能指针赋值
	shared_ptr<int>p(new int(42));
	int* q = p.get();
	{
		shared_ptr<int>q;
	} //q被销毁,所指向的内部被释放了
	int foo = *p; //未定义 p所指向的内存已经被释放了
	//使用get将指针的访问权限传递给代码,你只有在确定代码不会delete指针的情况下,才可以使用get


	//其他shared_ptr操作
	shared_ptr<int>p(new int(30));
	p.reset(new int(1024)); //p指向一个新的对象
	if (!p.unique())
		p.reset(new string(*p)); //我们不是唯一用户,分配新的拷贝

}
//传递unique_ptr参数和返回unique_ptr
unique_ptr<int>clone(int p) {
	return unique_ptr<int>(new int(p));
}
unique_ptr<int>clone(int p) {
	unique_ptr<int>ret(new int(p));
	return ret;
}

//unique_ptr
void test03() {
	unique_ptr<double>p1;
	unique_ptr<int>p2(new int(42));
	unique_ptr<string>p1(new string("hello"));
	//unique_ptr<string>p2(p1); 错误,unique_ptr不支持拷贝
	//p3 = p2; 错误unique_ptr不支持赋值

	unique_ptr<string>p2(p1.release());//使用release将p1置为空
	p2.reset(p2.release()); //reset释放了p2原来指向的内存,返回一个指针
}


//weak_ptr
void test04() {
	auto p = make_shared < int>(42);
	weak_ptr<int>wp(p); //wp弱共享p,p的引用计数未改变

}


//动态数组
void test05() {
	int* pia = new int[10];
	int* pia2 = new int[10]();
	string* psa = new string[10];
	string* psa2 = new string[10]();
	delete[] pia;

	typedef int arrt[42];
	int* p = new arrt;
	delete[] p;
	
	//智能指针和动态数组
	unique_ptr<int[]>up(new int[10]);
	up.release();
	
	//当unique_ptr指向一个数组时,可以用下标运算符来访问数组中的元素
	for (size_t i = 0; i != 10; i++) {
		up[i] = i;
	}


	//与unique_ptr不同,,shared_ptr不直接支持管理动态数组
	shared_ptr<int>sp(new int[10], [](int* p) {delete[] p; });
	sp.reset(); //使用我们提供的lambda释放数组

	//shared_ptr没有定义下标运算符,并且不支持指针的算术运算
	for (size_t i = 0; i != 10; i++) {
		*(sp.get() + i) = i; //使用get来获取一个内置指针
	}
}

//allocator类
void test06() {
	allocator<string>alloc; //可以分配string的allocator对象
	auto const p = alloc.allocate(10); //分配n个为初始化的string
	auto q = p;
	alloc.construct(q++);
	alloc.construct(q++, 10, 'c');
	cout << *p << endl;
	cout << *q << endl;
	while (q != p) {
		alloc.destroy(--q); //释放我们真正构造的string
	}

}


//文本查询程序


int main() {
	system("pause");
	return 0;
}

标签:string,int,动态内存,new,shared,unique,ptr
来源: https://www.cnblogs.com/best-you-articles-040612/p/16028922.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有