C++基础(十一)智能指针之unique
正文:
前一篇文章引见了共享指针shared_ptrVff0c;那篇引见另一种智能指针Vff1a;unique_ptr。
1、创立取shared_ptr差异Vff0c;C++11并无供给类似std::make_shared的范例库函数来返回一个unique_ptrVff0c;但是C++14供给了类似的库函数Vff1a;std::make_uniqueVff0c;语法如下Vff1a;
std::make_unique<类型>(参数列表)仍然以Person类为例Vff1a;
class Person { public: Person(const std::string& strName, int iAge) :m_strName(strName), m_iAge(iAge){} ~Person(){ std::cout << "Person析构, name=" << m_strName << std::endl; } ZZZoid PrintInfo(){ std::cout << "姓名Vff1a;" << m_strName << ", 年龄Vff1a;" << m_iAge << std::endl; } priZZZate: std::string m_strName; int m_iAge; };主函数如下Vff1a;
int _tmain(int argc, _TCHAR* argZZZ[]) { { std::unique_ptr<Person> p1 = std::make_unique<Person>("ye", 30); p1->PrintInfo(); } system("pause"); return 0; }执止结果Vff1a;
很简略Vff01;一旦p1的做用域消失Vff0c;便会主动开释内存。
2、所有权转移及内容清空从unique的字面就能了解Vff0c;那品种型的指针Vff0c;不能取其余指针一起共享内存对象Vff0c;只能惟一。假如实的须要Vff0c;只能将所有权转移Vff0c;转移后本来的指针无效。
转移所有权Vff0c;有两种方式Vff1a;
Vff08;1Vff09;p.release()p为unique_ptr指针Vff0c;放弃对指针的控制权Vff0c;返回指针Vff0c;并将p置为空。
看代码Vff1a;
int _tmain(int argc, _TCHAR* argZZZ[]) { { Person* p = nullptr; { std::unique_ptr<Person> p1 = std::make_unique<Person>("ye", 30); p = p1.release(); if (p1) std::cout << "p1非空" << std::endl; else std::cout << "p1已空" << std::endl; } p->PrintInfo(); } system("pause"); return 0; }执止结果如下Vff1a;
那里Vff0c;正在部分领域内定了一个普通的指针pVff0c;接着创立一个unique_ptr指针p1Vff0c;紧接着用p1.release(留心那里是"."Vff0c;不是"->")将p1的控制权转移给p。可以看到Vff0c;当p1的做用域完毕后Vff0c;并无主动开释对象的内存。那是因为Vff0c;正在颠终release后Vff0c;p1本来的内存对象曾经不再和智能指针绑定Vff0c;也就无奈通过智能指针主动开释。
当p的做用域完毕后Vff0c;也没有主动开释对象。那是因为p是普通指针Vff0c;尽管它的对象是从智能指针来的Vff0c;但是想要开释Vff0c;还是须要手动deleteVff0c;假如把p改成智能指针就可以作到主动开释。
但是须要留心一点Vff0c;release返回是普通指针Vff0c;假如要用智能指针接管Vff0c;则须要转换一次。
代码如下Vff1a;
int _tmain(int argc, _TCHAR* argZZZ[]) { { std::unique_ptr<Person> p; { std::unique_ptr<Person> p1 = std::make_unique<Person>("ye", 30); p = std::unique_ptr<Person>(p1.release()); //那里不能间接p = p1.release(); } p->PrintInfo(); } system("pause"); return 0; }执止结果如下Vff1a;
那里Vff0c;用unique_ptr的指针p来接管p1所指向的对象Vff0c;当p的做用域消失Vff0c;则会主动开释内存Vff0c;挪用析构函数Vff0c;打印相关信息。
Vff08;2Vff09;p.reset()/p.reset(k)p为unique_ptr指针Vff0c;若不传参数Vff0c;则间接将p置空Vff1b;若供给了普通指针kVff0c;则将p指向k的内存。
看代码Vff1a;
int _tmain(int argc, _TCHAR* argZZZ[]) { { std::unique_ptr<Person> p = std::make_unique<Person>("zhao", 40); { std::unique_ptr<Person> k = std::make_unique<Person>("ye", 30); p.reset(k.release()); //那里p副原指向的对象"zhao"不再有智能指针指向它Vff0c;所以会主动开释 if (k) std::cout << "k不为空" << std::endl; else std::cout << "k为空" << std::endl; } p->PrintInfo(); p.reset(); if (p) std::cout << "p不为空" << std::endl; else std::cout << "p为空" << std::endl; } system("pause"); return 0; }执止结果如下Vff1a;
步调中Vff0c;先创立了一个对象为"zhao"的unique_ptr指针pVff0c;紧接着创立一个对象为"ye"的unique_ptr指针kVff0c;再执止语句p.reset(k.release())。此时Vff0c;k的对象所有权会交给pVff0c;而p本来指向的对象因为再没有任何智能指针指向它Vff0c;所以会主动开释Vff0c;于是打印了"zhao"的析构信息。k挪用了releaseVff0c;曾经为空Vff0c;用if判断可以验证。紧接着打印p的信息Vff0c;为之前k的对象"ye"Vff1b;再执止p.reset()Vff0c;未传任何参数Vff0c;所以p间接被置空Vff0c;用if判断可以验证。
3、部分unique_ptrVff0c;可以做为返回值返回那个特征和unique_ptr不能赋值有一些斗嘴Vff0c;但是认实想想也很折法。
部分的unique_ptr正在返回时Vff0c;代表其行将消失Vff0c;做为返回值返回后Vff0c;指针仍然只要一份Vff0c;彻底折乎unique的特性。代码如下Vff1a;
std::unique_ptr<Person> GetPerson(const std::string& strName, int iAge) { std::unique_ptr<Person> p = std::make_unique<Person>(strName, iAge); return p; } int _tmain(int argc, _TCHAR* argZZZ[]) { { std::unique_ptr<Person> p = GetPerson("ye", 30); p->PrintInfo(); } system("pause"); return 0; }执止结果Vff1a;
4、不能间接做为参数Vff0c;须要以引用/const引用的方式做为参数unique_ptr不能间接做为参数Vff0c;须要用引用。
函数界说时没问题Vff0c;但是一旦挪用就会编译报错。
看代码Vff1a;
ZZZoid PrintInfo(std::unique_ptr<Person> pPerson) //那里间接用的是unique_ptr { pPerson->PrintInfo(); } int _tmain(int argc, _TCHAR* argZZZ[]) { { std::unique_ptr<Person> p = std::make_unique<Person>("ye", 30); PrintInfo(p); //假如将那一句注释掉Vff0c;编译会乐成 } system("pause"); return 0; }编译结果如下Vff08;ZZZs2013Vff09;Vff1a;
批改PrintInfo函数Vff0c;如下Vff1a;
ZZZoid PrintInfo(std::unique_ptr<Person>& pPerson) //参数改成为了引用 { pPerson->PrintInfo(); }主函数稳定Vff0c;运止结果如下Vff1a;
至此Vff0c;C++11提出来的两个简略便捷易用的智能指针shared_ptr和unique_ptr引见完结。其真都很简略Vff0c;多用几屡次就会。