C++ 智能指针

发布时间:2024年01月10日

智能指针概述

是什么:

智能指针是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<memory>

class Pointers {
	public:
		Pointers()=default;
        Pointers(std::string name):name(name){
	        std::cout << "Pointers is constructor:" <<name<< std::endl;
        }
        ~Pointers() {
	        std::cout << "Pointers is destroy:" <<name<< std::endl;
        }
		void info()const {
			std::cout << "Pointers name:" << name<<std::endl;
		}
		std::string getName()const {
			return name;
		}
		void setName(const std::string& name) {
			this->name = name;
		}
		void setSName(std::shared_ptr<Pointers> c) {
			w_ptr_p= c;
		}

private:
	std::string name{"First"};   //	std::string name = { "First" };
	std::weak_ptr<Pointers> w_ptr_p;
};

创建方法(有三种,不包括weak_ptr):


	/*智能指针第一种创建方法*/
	Pointers* p = new Pointers("A");
	std::unique_ptr<Pointers>u_c_p{ p };
	p = nullptr;


	/*智能指针第二种创建方法*/
	std::unique_ptr<Pointers>u_c_p1(new Pointers("B"));   //隐式创建类


	/*智能指针第三中创建方法*/
	std::unique_ptr<Pointers>u_c_p2 = std::make_unique<Pointers>();

reset()函数:

? ? ? ? 该方法用于释放智能指针所指向的资源。当调用?reset?方法时,智能指针会将其内部的计数器减一,如果计数器减至零,则会自动释放其所指向的资源。

unique_ptr指针用法:

move()函数:
? ? ? ? std::unique_ptr不能复制,只能move:

????? 这个函数用于将?unique_ptr?的所有权转移给另一个?unique_ptr。当一个?unique_ptr?调用?move()?函数后,它就会变成一个空指针,而所有权则转移给了另一个?unique_ptr

void uniq_ptr_pass_value(std::unique_ptr<Pointers> ptr) {
	ptr->setName("value");
	std::cout << "通过move传递,原始智能指针失效:" << ptr->getName() << std::endl;
}

int maint(){
	std::unique_ptr<Pointers> pt = std::make_unique<Pointers>("pt");
	uniq_ptr_pass_value(move(pt));

    uniq_ptr_pass_value(std::make_unique<Pointers>());        //相当于调用了move


    pt->->info();   //报错,  通过move传递后,pt变成空指针
}



???????通过move(),将unique_ptr转换为shared_ptr :
	unique_ptr<Pointers> c_p = make_unique<Pointers>("yy");
	shared_ptr<Pointers>s_p = move(c_p);
unique_ptr与函数:

? ? ? ? 因为unique_ptr不能复制, 所以除了move(),还可以引用的方式作为函数参数。此时需要注意有const和没有const的情况。

void uniq_ptr_ref(std::unique_ptr<Pointers>& ptr) {
	ptr.reset();        //没有加const时可以调用reset();
}
void uniq_ptr_refconst(const std::unique_ptr<Pointers>& ptr) {
	ptr.reset();        //有const限定符时会报错,
}

int main(){
    
    std::unique_ptr<Pointers> c_p_1 =std::make_unique<Pointers>("aa");
    uniq_ptr_ref(c_p_1);        //此函数会释放c_p_1指向的资源并把指针c_p_1置为空
    c_p_1->info();              //报错,c_p_1为空。
    
    std::unique_ptr<Pointers> c_p_2 =std::make_unique<Pointers>("bb");
    uniq_ptr_refconst(c_p_2);
    c_p_2->info();              //正常输出
}

shared_ptr指针用法:

use_count()函数:

? ? 该函数返回指向由?shared_ptr?管理的对象的共享所有权的引用计数。

	shared_ptr<Pointers> c_p_1 = make_shared<Pointers>();
	shared_ptr<Pointers> c_p_2 = c_p_1;
	shared_ptr<Pointers> 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
shared_ptr与函数:
void shared_ptr_value(shared_ptr<Pointers> ptr) {
	cout << "func use_count: " << ptr.use_count() << endl;    
}
void shared_ptr_ref(shared_ptr<Pointers>& ptr) {
	cout << "func use_count: " << ptr.use_count() << endl;
}
void shared_ptr_ref_const(const shared_ptr<Pointers>& ptr) {
	cout << "func use_count: " << ptr.use_count() << endl;
    //ptr.reset();         //这里不能被reset,因为有const限制
}

int main(){
       std::shared_ptr<Pointers> c_p_1=std::make_shared<Pointers>("cc");

        shared_ptr_value(c_p_1);                       //输出2
        std::cout<<c_p_1.use_count()<<std::endl;        //输出1
        
        shared_ptr_ref(c_p_1);                          //输出1
        shared_ptr_ref_const(c_p_1);                    //输出1


}

weak_ptr:

? ? ? ? weak_ptr创建

? ? ? ? weak_ptr指针不能直接创建,通过指向shared_ptr得到weak_ptr指针。

	shared_ptr<Pointers>s_ptr_p1 = make_shared<Pointers>("ff");
	weak_ptr<Pointers>w_ptr_p1{ s_ptr_p1 };    //得到一个weak_ptr指针

    std::cout<<s_ptr_p1.use_count()<<std::endl;        //输出1,weak_ptr不会增加shared_ptr的计数


    
? ? ? lock()函数

????????lock()?函数的主要用途是尝试获取对对象的访问权。如果?std::weak_ptr?所指向的对象仍然存在,那么?lock()?函数将返回一个指向该对象的?std::shared_ptr,并且该?std::shared_ptr?的引用计数加一。如果对象不存在,那么?lock()?函数将返回一个空的?std::shared_ptr

	shared_ptr<Pointers>s_ptr_p = make_shared<Pointers>("hh");    
    
    shared_ptr<Pointers>s_ptr_p1(new Pointers("gg"));

    weak_ptr<Pointers>w_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::endl;            //输出2
    } else {  
            // 对象已经被删除,不能使用它  
            std::cout << "sptr2 points to an invalid object\n";  
    }                            
shared_ptr死循环问题:

????????在使用?std::shared_ptr?时没有正确地管理共享所有权,可能会导致死循环问题。死循环问题通常发生在两个或多个?shared_ptr?对象相互引用时,导致它们之间的引用计数永远不会减少到零,从而导致程序无法正常结束。

#include<iostream>
#include<memory>

class Pointers {
	public:
		Pointers()=default;
        Pointers(std::string name):name(name){
	        std::cout << "Pointers is constructor:" <<name<< std::endl;
        }
        ~Pointers() {
	        std::cout << "Pointers is destroy:" <<name<< std::endl;
        }

		void setName(std::shared_ptr<Pointers> c) {
			m_sptr= c;
            //m_wptr=c;
		}

private:
	std::string name{"First"};   //	std::string name = { "First" };
	//std::weak_ptr<Pointers> m_wptr;
    std::shared_ptr<Pointers> m_sptr;
};


int main(){

        std::shared_ptr<Pointers> s_ptr_p= std::make_shared<Pointers>("jj");
        std::shared_ptr<Pointers> s_ptr_p1= std::make_shared<Pointers>("kk");
        //创建了两个shared_ptr<Pointers>

        s_ptr_p->setName(s_ptr_p1);        
        s_ptr_p1->setName(s_ptr_p);
        //两个shared_ptr对象相互引用,  此时程序会进入死循环,永远不能释放这两个指针


        //此时,可用weak_ptr指针来避免死循环。把Pointers类的成员变量-shared_ptr换成weak_ptr就可以了
        

}





文章来源:https://blog.csdn.net/qq_48757944/article/details/135078216
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。