C++ STL Smart Pointer 智能指针(二)unique_ptr

  unique_ptr实现了独占式拥有概念,它可以保证一个对象和其相应的资源同一时间只被一个pointer拥有。一旦拥有者被销毁或变成empty,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应的资源亦会被释放。

1.使用unique_ptr

#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main(){
    unique_ptr<string> up(new string("nico"));
    (*up)[0]='N';
    up->append("lai");
    cout<<*up<<endl;
}

输出:

Nicolai

 

2.转移unique_ptr的拥有权

以下的代码是错误的:

std::string* sp=new std::string("hello");
std::unique_ptr<std::string> up1(sp);
std::unique_ptr<std::string> up2(sp);

up1和up2拥有了同样的对象。

unique_ptr<A> up1(new A("a1"));
unique_ptr<A> up2(up1); //Error:up1 and up2 own same data

这里的up2不可以成为原对象的另一个拥有者。

 

正确的转移方法:

unique_ptr<A> up1(new A("a1"));
unique_ptr<A> up2(move(up1));
unique_ptr<A> up3;
up3=move(up2);

 

3.被当作成员

 a.h

#ifndef A_H
#define A_H
#include <iostream>
#include <string>

using namespace std;

class A
{
public:
    A(string n);
    A(int n);
    ~A();
    int a=0;
    string s="a";
};

#endif // A_H

a.cpp

#include "a.h"

A::A(string n)
{
    s=n;
}

A::A(int n){
    a=n;
}

A::~A(){
    cout<<"delete "<<s<<endl;
}

b.h

#ifndef B_H
#define B_H
#include <iostream>
#include "a.h"
#include <string>
#include <memory>

using namespace std;

class B
{
public:
    B(int val1,int val2);
    B(const B& x);
    B& operator =(const B& x);
    void print();
private:
    unique_ptr<A> ptr1;
    unique_ptr<A> ptr2;
};

#endif // B_H

b.cpp

#include "b.h"

B::B(int val1,int val2):ptr1(new A(val1)),ptr2(new A(val2))
{

}
B::B(const B &x):ptr1(new A(*x.ptr1)),ptr2(new A(*x.ptr2)){

}
B& B::operator =(const B& x){
    *ptr1=*x.ptr1;
    *ptr2=*x.ptr2;
    return *this;
}
void B::print(){
    cout<<"p1: "<<ptr1->a<<" p2: "<<ptr2->a<<endl;
}

main函数

int main(){
    B b(10,1);
    b.print();
}

输出:

p1: 10 p2: 1
delete a
delete a

  对于B,你可以不写析构函数,因为unique_ptr会为你做了该做的事。你还必须写出copy构造函数和赋值操作符;此二者的默认版本会拷贝复制成员,而在此那是不可能的。如果你没有自行提供它们,Class B将只能提供move语义。

4.对付Array

  基于C语言以来的规定,C++无法区分指针是“指向单对象”还是“指向array”。C++规定,对于数组应该使用delete[]而不是delete。所以以下语句是错误的:

std::unique_ptr<std::string> up(new std::string[10]);

  C++标准库为unique_ptr提供了一个偏特化的版本用来处理array,这个版本会在遗失其所指对象的拥有权时,对该对象调用delete[]。使用方法如下:

int main(){
    unique_ptr<string[]> up6(new string[10]);
    up6[0]="aaa";
    //cout<<*up<<endl;//Error
    cout<<"up6[0]:"<<up6[0]<<endl;
}

  然而,这个版本的接口稍有不同。它不再提供操作符*和->,而改提供操作符[]。

  这个class不接受派生类型的array作为初值,因此起不到多态的作用。

 

posted @ 2020-06-15 23:01  啸傲风月  阅读(198)  评论(0编辑  收藏  举报