unique_ptr
uniqut_ptr排他性拥有权的智能指针,即一个对象资源只能同时被一个unique_ptr指向
使用
- 简单使用
unique_ptr<int> p1(new int(3));
- 排他性
unique_ptr<int> p1(new int(3));
unique_ptr<int> p2=p1; // 会出错
- 为什么会出错?
1.1. 为了完成语义上的unique
,代码中将拷贝构造函数/赋值运算符给delete
了,导致无法调用。类似下面:
/*初始化,使用的是拷贝构造函数,不是赋值运算符*/
class A{
public:
A(){}
A& operator=(const A& other)=delete ;
A(const A& other)=delete ;
};
int main() {
A a;
A b;
b=a; //出错,赋值运算符给delete
A c(a);// 出错,拷贝构造函数delete
A d=a;// 出错,拷贝构造函数delete[初始化,使用的是拷贝构造函数,不是赋值运算符]
}
- 控制权转移:
move
int main() {
unique_ptr<int> p1(new int(1));
unique_ptr<int> p3=move(p1); //p1不再拥有控制权
if(p1){
cout<<"p1"<<endl;//不会运行
}
else{
cout<<"p3"<<endl; //会运行
}
return 0;
}
- 为什么这边又可以复制了: 因为
move
把原对象(示例中是a)变成右值,回去调用对应的移动构造函数
/移动赋值函数
。unique_ptr
在这两个函数中完成了控制权的转移
class A{
public:
A(){}
A& operator=(const A& other)=delete ;
A(const A& other)=delete ;
A& operator=(const A&& other){
//接受右值的,叫做:移动赋值函数
cout<<"move = "<<endl;
}
A(const A&& other){
//接受右值的,叫做:移动构造函数
cout<<"move constructor"<<endl;
}
};
int main() {
A a;
A b;
b=move(a); //输出move =
A c=move(a); //输出move constructor
A d(move(a)); //输出move constructor
return 0;
}
auto_ptr
已经废除,相当于使用move的unique_ptr
为何弃用 ref
auto_ptr采用copy语义来转移指针资源,转移指针资源的所有权的同时将原指针置为NULL,这跟通常理解的copy行为是不一致的(不会修改原数据),而这样的行为在有些场合下不是我们希望看到的。简单
auto_ptr<int> p1{new int(1)};
auto_ptr<int> p2=p1; // 相当于unique_ptr的:p2=move(p1),但是是通过赋值完成的
- 内部实现 ref
share_ptr
能够使用多个(智能)指针指向同一块地址,使用引用计数做内存管理
- 循环引用问题
class B;
class A{
public:
shared_ptr<B> b;
A(){cout<<"A"<<endl;}
~A(){cout<<"~A"<<endl;}
void set(const shared_ptr<B>& b){this->b=b;}
};
class B{
public:
shared_ptr<A> a;
B(){cout<<"B"<<endl;}
void set(const shared_ptr<A>& a){this->a=a;}
~B(){cout<<"~B"<<endl;}
};
int main() {
shared_ptr<A> p1{new A()};
shared_ptr<B> p2{new B()};
p1->set(p2);
p2->set(p1);
cout<<p1.use_count()<<endl; // output: 2
cout<<p2.use_count()<<endl; // output: 2
// 不会调用析构函数,因为引用计数不为0
return 0;
}
- 可以看到,
new A()
申请的空间有2个指针指向它; 同理new B()
。因为引用计数不为0,所以不会释放这两块空间
weak_ptr
搭配shared_ptr解决循环引用,weak_ptr只引用,不计数
class B;
class A {
public:
weak_ptr<B> b; //这里改成weak_ptr
A() { cout << "A" << endl; }
~A() { cout << "~A" << endl; }
void set(const shared_ptr<B> &b) { this->b = b; }
};
class B {
public:
weak_ptr<A> a; //这里改成weak_ptr
B() { cout << "B" << endl; }
void set(const shared_ptr<A> &a) { this->a = a; }
~B() { cout << "~B" << endl; }
};
int main() {
shared_ptr<A> p1{new A()};
shared_ptr<B> p2{new B()};
p1->set(p2);
p2->set(p1);
cout << p1.use_count() << endl; // output: 1
cout << p2.use_count() << endl; // output: 1
// 会调用析构函数,输出
/*
A
B
1
1
~B
~A
* */
return 0;
}