c++-------动态内存与智能指针(记录)

/*-----------StrBlob.h------------*/
#ifndef _STRBLOB_DATA_
#define _STRBLOB_DATA_

#include<iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

class StrBlobPtr;
class StrBlob;

class StrBlob
{
public:
	typedef string::size_type size_type;
	friend class StrBlobPtr;
	StrBlob() :data(make_shared<vector<string>>()) {};     //initializer_list只是保证可以传动态的形参,可以用vector来装
	StrBlob(vector<string> pri):data(make_shared<vector<string>>(pri)) {};
	StrBlob(initializer_list<string> il) :data(make_shared<vector<string>>(il)) {};
	
	size_type   size() const { return data->size(); }  //data是个指针,所以得用->
	bool empty() const { return data->empty(); }
	void push_back(const string &t) { data->push_back(t); }
	void pop_back() { data->pop_back(); };
	
	//元素访问,check先检查是否是空值
	string &front() { check(0, "front on empty StrBlob");   return data->front(); }
	string &back() { check(0, "back on empty StrBlob"); return data->back(); }

	//无法仅按返回类型进行重载函数,因此加const就知道是const版得重载函数
	string front()const; 
	string back()const;

	StrBlobPtr begin();
	StrBlobPtr end(); 
	

	~StrBlob() {};

private:
	shared_ptr<vector<string>> data;   //创建一个智能指针,指向vector<string>;允许多个指针指向同一个对象
	
	//如果data[i]不合法,将抛出一个异常
	void check(size_type i, const string msg) const;
};

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

string StrBlob::front()const
      { check(0, "front on empty StrBlob"); 
         return data->front();
      };
string StrBlob::back()const
       { check(0, "back on empty StrBlob"); 
        return data->back(); 
       };


class StrBlobPtr
{
public:
	StrBlobPtr() :curr(0) {};
	StrBlobPtr(StrBlob &a, size_t sz = 0) :
		wptr(a.data), curr(sz) {};
	string &deref()  const;
	StrBlobPtr &incr();
	


private:

	shared_ptr <vector<string>> check(size_t i, string msg) const;
	weak_ptr <vector<string>>  wptr;
	size_t curr;

};


shared_ptr <vector<string>> StrBlobPtr::check(size_t i, string msg) const
{
	auto ret = wptr.lock();
	if (!ret)
		throw runtime_error("unbound StrBlobPtr");
	if (i >= ret->size())
		throw out_of_range(msg);
	return ret;


}


string &StrBlobPtr::deref() const
{
	auto p = check(curr,"dereference past end");
	return (*p)[curr];

}

StrBlobPtr &StrBlobPtr::incr()
{
	auto p = check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;

}

StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); };
StrBlobPtr StrBlob::end() { auto ret = StrBlobPtr(*this, data->size()); return ret; };



#endif // !_STRBLOB_DATA_


/*------------main.cpp-------------*/

#include<iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <memory>
#include "StrBlob.h"

using namespace std;

vector<int>  *exchange(const vector<int> put);
shared_ptr<vector<int>>  my_exchange(const vector<int> put);

void _connect_s(const string &p, const string &p1, string *o);
bool b();
//void end_connect(connection *y);
void deleter(int *ptr);


void main()
{
	StrBlob b1;
	int input;
	vector<int> get;
	//std::cout << get->size()<<endl;
	//while (cin >> input)
	//{
	//	get.push_back(input);
		//get.push_back(input);
	//}
	
	vector<int> *_change=exchange(get);//现在_change指向了new的那一片内存;当用完_change时,需要delete _change;
	                                     //否则那片内存还在,会导致内存泄漏

	for (auto c : *_change)
		std::cout << c << endl;

	//delete _change;
	
	auto g_change=my_exchange(get);
	vector<decltype(g_change)> f;
	for (auto c1 : *g_change)   //记住g_change是个智能指针,它还是指针,所以得解引用
	{
		std::cout << c1 << endl;   //其实c是它的引用,就是它本身,c1是局部变量,也是g_change的引用,
		                        //当用完之后自动会被消除,从而那片内存也会被消除,但是书上说好像是拷贝才可以
		                         //引用不行,引用就是它本身,并没有指向那片内存,它不是个对象
		                         //c1用完自动被释放,从而那片内存也会被释放

	}
	f.push_back(g_change);
	f.erase(f.begin());   //为了删除g_change所指的那片内存,但我感觉前面用c1已经删除了


	//cout << b1.size() << endl;
	
	if (b())
		std::cout << "yes" << endl;

	shared_ptr<int> p(new int(10), deleter);
	shared_ptr<int> p1;
	p1 = p;   //当加了这个之后,就不会调用deleter,那我自己写个delete函数干嘛呢?
	p= make_shared<int>(15);   //当之前对10的那个内存的引用计数为0时,那么就删除10的那个内存,此时调用deleter这个函数
	std::cout << *p;

	//unique_ptr <int> ijj(new int(5));
	//unique_ptr <int> jii(ijj);   //unique_ptr不允许直接拷贝和赋值
	
	ifstream file2_open("C:\\Users\\信计捡球员\\Desktop\\测试\\测试\\file_name2.txt", ifstream::in);


	vector<string> _phones;
	string _data_line;
	//好好理解下面这段代码
	istringstream _iss;
	while (getline(file2_open, _data_line))
	{
		string p_name;
		_iss.str(_data_line);
		while (_iss >> p_name)
		_phones.push_back(p_name);
		
	
	}

	cout << "----------------------" << endl;
	StrBlob jpp(_phones); 
	StrBlobPtr kpp(jpp);
	int n = jpp.size();
	while (n--)
	{
		cout << kpp.deref() << endl;
		kpp.incr();
	}

	int *kop = new int[10];
	shared_ptr <int> sp(new int[10], [](int *p) {delete[]p; });  //自制lambda释放数组

	sp.reset(); 
	
	string *koo = new string[10];
	//string *iop=koo; //上面这种是无法初始化string *;必须说明维度,但new就可以
	_connect_s("你是", "?", koo);  //&koo就相当于koo,也是这个数组的首地址,其实传参传的就是首地址
	                                    //因为形参我写的有问题,是*o[];其实就是o指向string指针的数组,即里面存的是指针
	                                      //我现在改一下
	cout << (koo)[0];
	std::system("pause");
}

void _connect_s(const string &p, const string &p1,string *o)   //string o[]代表的是string *,指的是o的首地址
{                                                              //而string (*o)[]代表的是一个数组指针,它指向一个数组
	*(o) = p + p1;                                       //但这样string (*koo)[10]传不进来,一个是string (*)[10]
	                                      //一个是string (*)[],二者不匹配,后面会学到传任意大小的数组,
	                                     //若想可行,就必须设形参是string (*)[10]
	                 //还有一种,就是如果传任意大小的东西,就是实参不用一个数组的指针,而是直接传其首地址进去,
	               //其实也是可以修改的
}








void deleter(int *ptr)
{
	delete ptr;
	ptr = nullptr;
	cout << "delete pointer" << endl;
}



bool b() {
	int *p = new int;
	return p;       //我也不知道作何解释,但是能编译出来 
}

vector<int>  *exchange(const vector<int> put)
{
	vector<int> *p = new vector<int>(put);
	
	return p;   //p虽然没了,但它指向得内存还在

}


shared_ptr<vector<int>>  my_exchange(const vector<int> put)
{
	shared_ptr<vector<int>> p = make_shared<vector<int>>(put);  //用了智能指针

	return p;   //此时p是智能指针,当返回p时,p被销毁,p的引用计数减为0,
	            //但返回p时有别的对象引用了p;因此p所指的那片内存还在;
	           //直到最后一个引用那片内存的对象被销毁为止;

	shared_ptr<int> goo(new int(42));   //引用计数为1
	
	int *yu = goo.get();        //此时这个指针也指向那片内存,但不是智能指针,它被释放,则那片内存也没了
	{   //新程序块
		//两个独立的shared_ptr指向相同的内存
		shared_ptr<int>(yu);   //此时yu是一个智能指针了

	}   //但yu的那个智能指针是局部的,也引用计数为1;程序酷爱结束,它就销毁了,从而那片内存也被销毁
	int foo = *goo;    //错误,此时那片内存已经被释放了
	

}

struct destination;
struct connection{};



//connection connect(destination *);
//void disconnect(connection);
//void f(destination &f)
//{
//	connection op = connect(&f);
//	shared_ptr<connection> k(&op, end_connect);   //当f退出时,(即使是异常而退出,connection会被正确关闭)
//	shared_ptr<connection> k1(&op, [](connection *p) {disconnect(*p); });  //lambda
//}
//
//void end_connect(connection *y)   //关闭函数
//{
//	disconnect(*y);
//
//};

/*------------------小纠结-----------------*/
#include<iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>

using namespace std;

void _connect_s(const string &p, const string &p1, string *o);
void _connect_j(const string &p, const string &p1, string(*o)[]);

void main()
{

	string koo[10];// = new string[10];

	string *_new_koo= new string[10];

	string(*kop)[10];

	//_connect_j("你是", "?", kop);   //一个是string (*)[]和string (*)[10]不匹配

	_connect_s_pointer("你是", "?", _new_koo);

	_connect_s("你是", "?", _new_koo);

	_connect_s("你是", "?", koo);       


	cout << (koo)[0];
	system("pause");
}

void _connect_s(const string &p, const string &p1, string &o)
{
	*(&o + 2) = p + p1;           //第一种是传首地址进去


}

void _connect_s_pointer(const string &p, const string &p1, string *o)
{
	*(o + 2) = p + p1;                   //传指针进去


}


void _connect_j(const string &p, const string &p1, string (*o)[])
{

	
	*(*o + 2) = p + p1;                  //传指针进去


}




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值