c++ 智能指针_C++ 智能指针

  1. 历史遗留项目可以继续使用裸指针维护
  2. 新C++项目,建议直接使用智能指针(shared_ptr,unique_ptr)
  3. 熟练使用智能指针写C++程序可以像C#一样舒服

问:Smart pointer 会不会比Raw pointer效率低?

  • 答:想把智能指针用成瓶颈的话,基本上是不可能的,不要过度担心

问:Smart pointer 不用自己管理内存了,是不是对c++程序员要求低了

  • 答:显然是要求更高了,想要用好智能指针的前提是会熟练使用裸指针,而且要了解智能指针的实现原理,要根据实际情况去选择shared_ptr及unique_ptr。智能指针使用不当同样会内存泄漏

笔记:unique_ptr使用

unique 顾名思义 ownership 唯一

  1. 推荐使用make_unique进行初始化(C++14)
std::unique_ptr<int> pTest = std::make_unique<int>(3);

2. 函数传递时避免使用unique_ptr作为函数参数,除非需要转移所有权到函数里面,一般通过Get函数获取裸指针去传递

void func1(std::unique_ptr<int> p){
	*p = 10;
}

void func2(int* p) {
	*p = 10;
}

int main() {
	std::unique_ptr<int> pInt = std::make_unique<int>(3);
	func2(pInt.get());
}

如果一定要使用unique_ptr进行传递,可以选择使用引用(不推荐,原因见文章末尾)

#include <memory>
void func1(std::unique_ptr<int>& p){
	*p = 10;
}

int main() {
	std::unique_ptr<int> pInt = std::make_unique<int>(3);
	func1(pInt);
}

3.unique_ptr经常作为返回值使用,设计模式中经常用到,异常安全

如工厂模式

class PizzaFactory {
public:
	enum PizzaType {
		HamMushroom,
		Deluxe,
		Hawaiian
	};

	static unique_ptr<Pizza> createPizza(PizzaType pizzaType) {
		switch (pizzaType) {
		case HamMushroom: return make_unique<HamAndMushroomPizza>();
		case Deluxe:      return make_unique<DeluxePizza>();
		case Hawaiian:    return make_unique<HawaiianPizza>();
		}
		throw "invalid pizza type.";
	}
};

或者Prototype原型模式

class RecordFactory
{
private:
	unordered_map<RecordType, unique_ptr<Record>, hash<int> > m_records;

public:
	RecordFactory()
	{
		m_records[CAR]    = make_unique<CarRecord>("Ferrari", 5050);
		m_records[BIKE]   = make_unique<BikeRecord>("Yamaha", 2525);
		m_records[PERSON] = make_unique<PersonRecord>("Tom", 25);
	}

	unique_ptr<Record> createRecord(RecordType recordType)
	{
		return m_records[recordType]->clone();
	}
};

笔记:shared_ptr

  • 我用c++开发服务器端时,因为要并发,经常用到shared_ptr
  • 初始化同样使用make_shared
std::shared_ptr<int> pInt = std::make_shared<int>(3);
  • 避免循环引用的坑(你中有我,我中有你。解决方法是将其中一个改成weak_ptr)
struct A;
struct B;
struct B {
	std::shared_ptr<int> pA;
};
struct A {
	std::shared_ptr<int> pB;
};
  • 使用智能指针时,避免使用new 裸指针
  • 我喜欢将shared_ptr 放到std::vector<>中 ~ ~

什么时候用shared_ptr,什么时候用unique_ptr?

  • 我一直在思考这个问题
  • 其实判别很简单,就是ownership,独占所有权就用unique_ptr ,共享就shared
  • 想不明白的时候,我一般先会使用uniqe_ptr ,当编译器编译不通过的时候,我再换shared_ptr
  • 更懒的时候,我直接用shared_ptr 。后期我再重构

注意事项引用评论中烟落尘寰的回复

参数传递时,尽量不要使用智能指针的引用

分两种情况讨论:shared_ptr与unique_ptr。shared_ptr本身就不必要传递引用,因为不会发生所有权变化。而就unique_ptr来说,传递引用会造成:

  • 接受引用方对此资源是否具有所有权?如果有,则破坏了unique_ptr的独一所有权语义,应考虑move或者换成shared_ptr;如果没有,应考虑传递裸指针而非传递引用。
  • 接受引用方会否将资源长期持有?比如多线程之间资源传递。若有,该资源生命周期不被引用方控制,会造成隐形bug。

总结:正确使用智能指针的方式是(参考图片)

  1. 在函数中作为参数传递是,尽量避免使用智能指针,使用*或者引用,跟以前一样
  2. 尽量使用unique_ptr,他比shared_ptr更light
  3. 尽量使用makeshared/ make_unique 来代替new
  4. 不出现new 和 delete

b7bb5d7f3ffff55029c79af4986b89f9.png

未完待续...

参考:

守望:为何优先选用unique_ptr而不是裸指针?​zhuanlan.zhihu.com
https://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Prototype​en.wikibooks.org https://www.youtube.com/watch?v=UsrHQAzSXkA​www.youtube.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值