C++ Primer学习总结 第12章 动态内存

C++ Primer学习总结 第12章 动态内存



1、申请使用shared_ptr

int main() 
{
	shared_ptr<string> sp;//定义一个智能指针,但是sp现在还没申请空间
	string s("123");
	// *sp = s;       //无效
	// cout << *sp;
	
	sp = make_shared<string>(3,'a');//在动态内存中分配对象并初始化它
	cout << *sp << endl;
	*sp = s;
	cout <<*sp;
	
    return 0;
}




2、shared_ptr 计数

赋值、拷贝、向函数传递一个智能指针,函数返回智能指针都会增加当前智能指针的计数。

void show(shared_ptr<int> sp){cout << sp.use_count()<<endl; return }

int main() 
{
	shared_ptr<int>sp;//构造空职能指针
	cout << sp.use_count() << endl;//0


	sp = make_shared<int>(11);//赋值
	cout << sp.use_count() << endl;//1;


	shared_ptr<int> sp1(sp);//拷贝给第二个
	cout << sp.use_count() << endl;//2;


	shared_ptr<int> sp2;
	sp2 = sp;//赋值给第三个

	cout << sp.use_count() << endl;//3
	cout << sp2.use_count() << endl;//3

	show(sp);//作为实参(拷贝)

}    




3、使用new动态申请内存
默认情况下,new申请的内存对象都是默认初始化的。

int main() 
{
	int *p1 = new int;//默认初始化
	cout << *p1 << endl;//随机值

	int *p2 = new int();//值初始化
	cout << *p2 << endl;

	int *p3 = new int(100);//直接初始化
	cout << *p3 << endl;

	string *p4 = new string(6,'a');//构造函数初始化
	cout << *p4 << endl;

	std::vector<int> *p5 = new vector<int> {0,1,2,3,4};//列表初始化
	for(auto x:*p5)cout << x << endl;
}





4、new申请的const对象必须初始化。

申请内置类型,必须用()初始化。如果申请类类型,如果该类对象有默认构造函数,可以默认初始化。如果没有,必须用其他的构造函数初始化。

class A{
public:	
	A(int v):v(v){}
	int v;
};
int main() 
{
	//const int *p1 = new const int;//错误,const必初始化
	const int *p1 = new const int();
	cout << *p1 << endl;

	const string *p2 = new const string;//有默认构造函数
	cout << *p2;
	
	// const A *p3 = new const A;//没有默认构造函数。
	const A *p3 = new const A(10);
	cout << p3->v << endl;
    return 0;
}




5、关于delete.
delete 只能删除指针,且该指针是由new申请的内存空间。
销毁给定指针指向的对象,释放对应的内存。

注意的问题:
1.不要忘记delete,内存永远不会归还给自由空间了。
2.不要使用已经释放掉的内存。
3.不要delete两次,自由空间有可能被破坏。

delete+nullptr一起使用,避免使用空悬指针。
但是仍然保护很有效,因为一个对象有可能被多个指针同时指向。




6、shared_ptr 和 new结合使用

shared_ptr的构造函数是explicit的,必须使用直接初始化形式。

    shared_ptr<int> p(new int(1));
	shared_ptr<int> p = new int(1);//错误,必须直接初始化





7、不要混用智能指针和内置指针。
智能指针绑定到内置指针上时,内存管理就交给智能指针了,一旦这样做了就不要再用内置指针访问了。
下面这段代码在cb上跑竟然指针p还在???
在VS上才成功。(被编译器安排了

void Fun(shared_ptr<int>p){
	
}
int main() 
{
	int *p = new int;
	*p = 10;
	cout << *p << endl;
	Fun(shared_ptr<int>(p) );
	cout << *p << endl;//未定义
}



8、不要用get初始化另一个智能指针或为智能指针赋值,+ 其他操作
(再次被编译器安排,和c++primer P414描述不一样)

void Fun(shared_ptr<int>p) {

}
int main()
{
	shared_ptr<int>p(new int(42));
	int *q = p.get();

	{
		shared_ptr<int>(q);
	}//wc,,,咋没释放???
		//Fun(shared_ptr<int>(q));
	//q被释放
	cout << *p << endl;
}


p.reset(new int(666));
p.unique();//是不是唯一的用户




9、unique_ptr对象初始化
由于unique_ptr “拥有”它的对象,所以不能拷贝和赋值,且只能通过内置指针通过括号()初始化它。
例外:可以用返回值为unique_str的函数去拷贝和赋值一个将要被销毁的unique_str;

unique_ptr<int> f(){
	return unique_ptr<int>(new int(22));
}
int main() 
{
	unique_ptr<int> p1(new int(11));
	cout << *p1 << endl;

	unique_ptr<int> p2;
	// p2 = p1;//错误

	p2 = f();
	cout << *p2 << endl;

    return 0;
}




10、unique_ptr对象的reset() 和 release()函数的用法


int main() 
{
	unique_ptr<int> p1(new int(1));

	unique_ptr<int> p2(p1.release());//p1放弃对指针的控制权(并不释放内存),返回指针值
	cout << *p2 << endl;//1
	cout << *p1 << endl;//未定义
	
	unique_ptr<int> p3(new int(3));
	cout << *p3 << endl;
	
	p3.reset(p2.release());//释放掉自己指针内存,重新控制p2.release()的指针
	cout << *p3 << endl;//1
	cout << *p2 << endl;//未定义

    return 0;
}




11、unique_ptr传递自己的删除器(shared_ptr类似)
对象构造了自己的删除器end_ptr
当对象析构的时候,会执行end_ptr(up中的int 指针)
输出2

void end_ptr(int *p){
	cout << *p + 1 << endl;
	delete p;
}
int main() 
{
	unique_ptr<int,decltype(end_ptr)*> up(new int (1),end_ptr);
}




12、weak_ptr
不控制对象生存期的智能指针,指向shared_ptr管理的对象。不影响shared_ptr的引用计数。

int main() 
{
	shared_ptr<int> sp(new int(3));
	weak_ptr<int>wp;
	wp = sp;

	cout << wp.use_count() << endl;//1

	cout << wp.expired() << endl;//use_count为0返回ture

	shared_ptr<int> sp2 = wp.lock();//通过weak_ptr获取一个shared_ptr对象

	cout << wp.use_count() << endl; //2

    return 0;
}





13、new分配动态数组
使用new分配的数组元素类型的指针 而不是 一个数组类型。

int main() 
{
	typedef int a[10];
	int *p1 = new a;
	int *p2 = new int[3];
	int *p3 = new int[3]();//p1,p2,p3并不是数组类型


	cout << *begin(p1);//错误,p1不是数组,只是首元素指针
	delete [] p1;//释放一个数组

    return 0;
}





14、使用智能指针管理动态数组注意shared_ptr 和 unique_str的区别

	unique_ptr<int[]> up(new int[5]);

	for(int i = 0;i<5;++i)
		up[i] = i+1;
	for(int i = 0;i<5;++i)
		cout << up[i] << endl;//unique_str支持下标操作

	shared_ptr<int> sp(new int[5],[](int *p){delete [] p;});//lambda,必须提供删除器

	for (int i = 0; i < 5; ++i)
	{
		*(sp.get() + i) = i+1;//不支持下标
		cout << *(sp.get() + i ) << endl;
	}




15、new 和 malloc的区别
数:运算符–库函数

返回类型:指针—void* (需转换)

分配失败:异常—NULL

分配内存+初始化(构造函数,)—只分配内存

内存区域:自由存储器—堆区

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值