智能指针是C++中用来管理动态内存的一种机制。它通过对指针对象进行封装,使得在特定的作49·47用域内自动管理内存的分配和释放。
智能指针的主要用途是解决C++中常见的内存泄漏和空悬指针问题。它提供了一种方便而安全地使用动态分配对象的方法。
在C++中,有三种智能指针类型:std::shared_ptr、std::unique_ptr和std::weak_ptr。
std::shared_ptr:是一种共享所有权的智能指针。它可以多个指针同时拥有同一个对象,对象只有在最后一个拥有者释放时才会被销毁。这种指针可以通过std::make_shared函数来创建,也可以使用new关键字来创建。
std::unique_ptr:是一种独占所有权的智能指针。只能有一个unique_ptr
指向某个对象。当unique_ptr
销毁时,其所指向的对象也会被自动删除。这种指针可以使用new关键字来创建,也可以通过std::make_unique函数来创建
std::weak_ptr:不拥有对象的所有权,只是对shared_ptr
的一个引用。它可以用来检测对象是否已被删除,并避免循环引用。
新建一个Pointers类来举例说明,类定义如下:
#include
class Pointers {
public:
Pointers()=default;
Pointers(std::string name):name(name){
std::cout << "Pointers is constructor:" <name = name;
}
void setSName(std::shared_ptr c) {
w_ptr_p= c;
}
private:
std::string name{"First"}; // std::string name = { "First" };
std::weak_ptr w_ptr_p;
};
/*智能指针第一种创建方法*/
Pointers* p = new Pointers("A");
std::unique_ptru_c_p{ p };
p = nullptr;
/*智能指针第二种创建方法*/
std::unique_ptru_c_p1(new Pointers("B")); //隐式创建类
/*智能指针第三中创建方法*/
std::unique_ptru_c_p2 = std::make_unique();
该方法用于释放智能指针所指向的资源。当调用 reset
方法时,智能指针会将其内部的计数器减一,如果计数器减至零,则会自动释放其所指向的资源。
这个函数用于将 unique_ptr
的所有权转移给另一个 unique_ptr
。当一个 unique_ptr
调用 move()
函数后,它就会变成一个空指针,而所有权则转移给了另一个 unique_ptr
。
void uniq_ptr_pass_value(std::unique_ptr ptr) {
ptr->setName("value");
std::cout << "通过move传递,原始智能指针失效:" << ptr->getName() << std::endl;
}
int maint(){
std::unique_ptr pt = std::make_unique("pt");
uniq_ptr_pass_value(move(pt));
uniq_ptr_pass_value(std::make_unique()); //相当于调用了move
pt->->info(); //报错, 通过move传递后,pt变成空指针
}
unique_ptr c_p = make_unique("yy");
shared_ptrs_p = move(c_p);
因为unique_ptr不能复制, 所以除了move(),还可以引用的方式作为函数参数。此时需要注意有const和没有const的情况。
void uniq_ptr_ref(std::unique_ptr& ptr) {
ptr.reset(); //没有加const时可以调用reset();
}
void uniq_ptr_refconst(const std::unique_ptr& ptr) {
ptr.reset(); //有const限定符时会报错,
}
int main(){
std::unique_ptr c_p_1 =std::make_unique("aa");
uniq_ptr_ref(c_p_1); //此函数会释放c_p_1指向的资源并把指针c_p_1置为空
c_p_1->info(); //报错,c_p_1为空。
std::unique_ptr c_p_2 =std::make_unique("bb");
uniq_ptr_refconst(c_p_2);
c_p_2->info(); //正常输出
}
该函数返回指向由 shared_ptr
管理的对象的共享所有权的引用计数。
shared_ptr c_p_1 = make_shared();
shared_ptr c_p_2 = c_p_1;
shared_ptr c_p_3{ c_p_2 };
cout << "c_p_1 use_count: " << c_p_1.use_count() << endl; //输出3
cout << "c_p_2 use_count: " << c_p_2.use_count() << endl; //输出3
cout << "c_p_3 use_count: " << c_p_3.use_count() << endl; //输出3
void shared_ptr_value(shared_ptr ptr) {
cout << "func use_count: " << ptr.use_count() << endl;
}
void shared_ptr_ref(shared_ptr& ptr) {
cout << "func use_count: " << ptr.use_count() << endl;
}
void shared_ptr_ref_const(const shared_ptr& ptr) {
cout << "func use_count: " << ptr.use_count() << endl;
//ptr.reset(); //这里不能被reset,因为有const限制
}
int main(){
std::shared_ptr c_p_1=std::make_shared("cc");
shared_ptr_value(c_p_1); //输出2
std::cout<
weak_ptr指针不能直接创建,通过指向shared_ptr得到weak_ptr指针。
shared_ptrs_ptr_p1 = make_shared("ff");
weak_ptrw_ptr_p1{ s_ptr_p1 }; //得到一个weak_ptr指针
std::cout<
lock()
函数的主要用途是尝试获取对对象的访问权。如果 std::weak_ptr
所指向的对象仍然存在,那么 lock()
函数将返回一个指向该对象的 std::shared_ptr
,并且该 std::shared_ptr
的引用计数加一。如果对象不存在,那么 lock()
函数将返回一个空的 std::shared_ptr
。
shared_ptrs_ptr_p = make_shared("hh");
shared_ptrs_ptr_p1(new Pointers("gg"));
weak_ptrw_ptr_p = s_ptr_p; //weak_ptr指向s_ptr_p
s_ptr_p1 = w_ptr_p.lock(); //如果w_ptr_p指向的对象存在,lock()函数返回有效的std::shared_ptr,并让s_ptr_p1的引用计数器加1,如果不存在就返回空的std::shared_ptr
if(s_ptr_p1){
// 对象仍然存在,可以安全地使用它
std::cout << s_ptr_p1.use_count()<
在使用 std::shared_ptr
时没有正确地管理共享所有权,可能会导致死循环问题。死循环问题通常发生在两个或多个 shared_ptr
对象相互引用时,导致它们之间的引用计数永远不会减少到零,从而导致程序无法正常结束。
#include
#include
class Pointers {
public:
Pointers()=default;
Pointers(std::string name):name(name){
std::cout << "Pointers is constructor:" < c) {
m_sptr= c;
//m_wptr=c;
}
private:
std::string name{"First"}; // std::string name = { "First" };
//std::weak_ptr m_wptr;
std::shared_ptr m_sptr;
};
int main(){
std::shared_ptr s_ptr_p= std::make_shared("jj");
std::shared_ptr s_ptr_p1= std::make_shared("kk");
//创建了两个shared_ptr
s_ptr_p->setName(s_ptr_p1);
s_ptr_p1->setName(s_ptr_p);
//两个shared_ptr对象相互引用, 此时程序会进入死循环,永远不能释放这两个指针
//此时,可用weak_ptr指针来避免死循环。把Pointers类的成员变量-shared_ptr换成weak_ptr就可以了
}