在C++11中通过引入智能指针的概念,使得C++程序员不需要手动释放内存
智能指针的种类
1)unique_ptr
2)shared_ptr
3)weak_ptr
auto_ptr已经被废弃
unique_ptr
- unique_ptr在任何给定的时刻,只能有一个指针管理内存
- 当指针超出作用域时,内存将自动释放
- 该类型指针不可Copy,只可以Move
三种创建方式
- 通过已有裸指针创建
- 通过new创建
- 通过std::make_unique创建(推荐)
unique_ptr可以通过get()获取地址
unique_ptr实现了->与*
- 可以通过->调用成员函数
- 可以通过*调用dereferencing
示例函数
class Cat {
public:
Cat(string name);
Cat() = default;
~Cat();
void cat_info() const {
cout << "cat inf name:" << name << endl;
}
string get_name() const {
return name;
}
void set_name(const string &name) {
this->name = name;
}
private:
string name{"Mimi"};
};
Cat::Cat(string name) :name(name) {
cout << "Constructor of Cat:" << name << endl;
}
Cat::~Cat() {
cout << "Destructor of Cat:"<<name << endl;
}
使用stack
int main() {
Cat c1("ok");
c1.cat_info();
{
Cat c2("yes");
c2.cat_info();
}
cout << "---------" << endl;
return 0;
}
结果
Constructor of Cat:ok
cat inf name:ok
Constructor of Cat:yes
cat inf name:yes
Destructor of Cat:yes
---------
Destructor of Cat:ok
使用原始指针
int main() {
//使用原始指针
Cat* c_p1 = new Cat("yy");
c_p1->cat_info();
{
Cat* c_p2 = new Cat("zz");
c_p2->cat_info();
delete c_p2;
}
delete c_p1;
cout << "---------" << endl;
return 0;
}
结果
Constructor of Cat:yy
cat inf name:yy
Constructor of Cat:zz
cat inf name:zz
Destructor of Cat:zz
Destructor of Cat:yy
---------
int main(){
unqie_ptr的三种创建方式
//第一种
Cat* c_p2 = new Cat("ok");
unique_ptr<Cat> u_c_p2{ c_p2 };
c_p2 = nullptr;
delete c_p2;
u_c_p2->cat_info();
//第二种
unique_ptr<Cat> u_c_p3{ new Cat("dd") };
u_c_p3->cat_info();
//第三种:推荐
unique_ptr<Cat> u_c_p4 = make_unique<Cat>();
u_c_p4->cat_info();
cout << "---------" << endl;
return 0;
}
结果
Constructor of Cat:ok
cat inf name:ok
Constructor of Cat:dd
cat inf name:dd
cat inf name:Mimi
---------
Destructor of Cat:Mimi
Destructor of Cat:dd
Destructor of Cat:ok
uniqet_ptr 与 函数调用
- unique_ptr是不可Copy,只可以Move
- 在做函数参数或者是返回值中一定要注意所有权
函数调用与unique_ptr注意事项
-
Passing by value
需要用move来转移内存拥有权
如果参数直接传入make_unique语句,自动转换为movevoid do_with_cat_passByValue(unique_ptr<Cat> c) { c->cat_info(); } int main(){ //1.pass by value unique_ptr<Cat> c1 = make_unique<Cat>("ff"); do_with_cat_passByValue(move(c1)); cout<<"--------"<<endl; } 结果 Constructor of Cat:ff cat inf name:ff Destructor of Cat:ff -------
-
Passing by reference
如果设置参数为const,则不能改变指向
reset()方法为智能指针清空方法void do_with_cat_passByReference(const unique_ptr<Cat> &c) { c->set_name("oo"); c->cat_info(); //c.reset(); } unique_ptr<Cat> c2 = make_unique<Cat>("ff2"); do_with_cat_passByReference(c2); 结果 Constructor of Cat:ff2 cat inf name:oo --------- Destructor of Cat:oo
-
return by value
指向一个local object
可以用作链式函数
shared_ptr
- shared_ptr计数指针,又称共享指针
shared_ptr创建了一个计数器与类对象所指的内存相关联
copy则计数器加一,销毁则计数器减一
api为use_count() - 与unique_ptr不同的是它可以共享数据
//常量类型
int main(){
shared_ptr<int> i_p_1 = make_shared<int>(10);
cout << "value:" << *i_p_1 << endl;
cout << "use count:" << i_p_1.use_count() << endl;
shared_ptr<int> i_p_2 = i_p_1;
cout << "value:" << *i_p_2 << endl;
cout << "use count:" << i_p_2.use_count() << endl;
i_p_2 = nullptr;
cout << "use count:" << i_p_1.use_count() << endl;
cout << "use count:" << i_p_2.use_count() << endl;
cout << "---------" << endl;
return 0;
}
结果
value:10
use count:1
value:10
use count:2
use count:1
use count:0
---------
int main() {
//自定义类型
shared_ptr<Cat> c_p_1 = make_shared<Cat>();
cout << "c_p_1 use count:" << c_p_1.use_count() << endl;
shared_ptr<Cat> c_p_2 = c_p_1;
shared_ptr<Cat> c_p_3 = c_p_1;
cout << "c_p_1 use count:" << c_p_1.use_count() << endl;
cout << "c_p_2 use count:" << c_p_2.use_count() << endl;
cout << "c_p_3 use count:" << c_p_3.use_count() << endl;
c_p_1 = nullptr;
cout << "c_p_1 use count:" << c_p_1.use_count() << endl;
cout << "c_p_2 use count:" << c_p_2.use_count() << endl;
cout << "c_p_3 use count:" << c_p_3.use_count() << endl;
cout << "------------" << endl;
return 0;
}
结果
c_p_1 use count:1
c_p_1 use count:3
c_p_2 use count:3
c_p_3 use count:3
c_p_1 use count:0
c_p_2 use count:2
c_p_3 use count:2
------------
Destructor of Cat:Mimi
shared_ptr与unique_ptr
- 不能将shared_ptr转换为unique_ptr
- unique_ptr可以转换为shared_ptr(通过move)
unique_ptr<Cat> get_unique_ptr() {
unique_ptr<Cat> p_cat = make_unique<Cat>("Local cat");
return p_cat;
}
int main() {
unique_ptr<Cat> c_p_1 = make_unique<Cat>("dd");
shared_ptr<Cat> c_p_2 = move(c_p_1);
cout << "c_p_2 use count:" << c_p_2.use_count() << endl;
//func:使用shared_ptr可以接收 unqiue_ptr
shared_ptr<Cat> c_p_3 = get_unique_ptr();
if (c_p_3) {
c_p_3->cat_info();
cout << "c_p_3 use count:" << c_p_3.use_count() << endl;
}
cout << "-----------" << endl;
return 0;
}
结果
Constructor of Cat:dd
c_p_2 use count:1
Constructor of Cat:Local cat
cat inf name:Local cat
c_p_3 use count:1
-----------
Destructor of Cat:Local cat
Destructor of Cat:dd
weak_ptr
- weak_ptr并不拥有内存所有权
- 不能调用->和解引用 *
weak_ptr为什么会存在
- A类中有一个需求需要存储其他A类对象的信息
如果使用shared_ptr, 那么在销毁时会遇到环形依赖问题
所以我们这里需要用一个不需要拥有所有权的指针来标记该同类对象
weak_ptr可以通过lock()函数来提升为shared_ptr
weak_ptr不会增加计数器的值
int main(){
shared_ptr<Cat> s_p_c1 = make_shared<Cat>("c1");
weak_ptr<Cat> w_p_c1(s_p_c1);
cout << "s_p_c1 use count:" << s_p_c1.use_count() << endl;
cout << "w_p_c1 use count:" << w_p_c1.use_count() << endl;
//lock()将weak_ptr转为shared_ptr
shared_ptr<Cat> s_p_c2 = w_p_c1.lock();
cout << "s_p_c1 use count:" << s_p_c1.use_count() << endl;
cout << "s_p_c2 use count:" << s_p_c1.use_count() << endl;
cout << "w_p_c1 use count:" << w_p_c1.use_count() << endl;
cout << "------------" << endl;
}
结果
Constructor of Cat:c1
s_p_c1 use count:1
w_p_c1 use count:1
s_p_c1 use count:2
s_p_c2 use count:2
w_p_c1 use count:2
------------
Destructor of Cat:c1
循环依赖问题
class Cat {
public:
Cat(string name);
Cat() = default;
~Cat();
void cat_info() const {
cout << "cat inf name:" << name << endl;
}
string get_name() const {
return name;
}
void set_name(const string &name) {
this->name = name;
}
void set_friend(shared_ptr<Cat> c) {
m_friend = c;
}
private:
string name{"Mimi"};
shared_ptr<Cat> m_friend;
};
int main(){
shared_ptr<Cat> c3 = make_shared<Cat>("c3");
shared_ptr<Cat> c4 = make_shared<Cat>("c4");
}
//结果
Constructor of Cat:c3
Constructor of Cat:c4
------------
Destructor of Cat:c4
Destructor of Cat:c3
int main(){
shared_ptr<Cat> c3 = make_shared<Cat>("c3");
shared_ptr<Cat> c4 = make_shared<Cat>("c4");
//环形依赖
c3->set_friend(c4);
c4->set_friend(c3);
}
//结果:没有调用析构函数
Constructor of Cat:c3
Constructor of Cat:c4
------------
将类中的shared_ptr m_friend 换成 weak_ptr m_friend,就可以解决环形依赖的问题
class Cat {
public:
Cat(string name);
Cat() = default;
~Cat();
void cat_info() const {
cout << "cat inf name:" << name << endl;
}
string get_name() const {
return name;
}
void set_name(const string &name) {
this->name = name;
}
void set_friend(shared_ptr<Cat> c) {
m_friend = c;
}
private:
string name{"Mimi"};
weak_ptr<Cat> m_friend;
};
int main(){
shared_ptr<Cat> c3 = make_shared<Cat>("c3");
shared_ptr<Cat> c4 = make_shared<Cat>("c4");
//环形依赖
c3->set_friend(c4);
c4->set_friend(c3);
}
结果
Constructor of Cat:c3
Constructor of Cat:c4
------------
Destructor of Cat:c4
Destructor of Cat:c3