1. 智能指针unique_ptr的基本使用
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Point
{
public:
Point(int x = 0, int y = 0)
:m_x(x), m_y(y)
{
cout << "constructor " << m_x << endl;
}
Point(const Point& rhs)
{
cout << "cocpy constructor" << endl;
this->m_x = rhs.m_x;
this->m_y = rhs.m_y;
}
Point& operator= (const Point& rhs)
{
cout << "operator =" << endl;
return *this;
}
~Point()
{
cout << "destructor " << m_x << endl;
}
int m_x;
int m_y;
};
void test1()
{
Point *p = new Point(1); //使用默认参数
unique_ptr<Point>up1(p); //托管普通指针
printf("p = %p\n", p);
printf("up1 = %p\n", up1.get()); //2者地址相同
}
void test2()
{
unique_ptr<Point>up2(new Point(2));
unique_ptr<Point>up3 = make_unique<Point>(3);
unique_ptr<Point>up4(make_unique<Point>(4)); //3 ,4, 5,是c++11 提供的初始化方法 ,演示一下
unique_ptr<Point>up5{make_unique<Point>(5)};
cout << up2.get()->m_x << endl; // 访问成员变量或者函数的两种方式
cout << up2->m_x << endl;
}
void test3()
{
unique_ptr<Point[]>up6(new Point[2]);
unique_ptr<Point[]>up7 = make_unique<Point[]>(2);
up6[1].m_x = 333;
cout << up6[1].m_x << endl; //这里是涉及指针知识 up[i] 等价于*(up+i) 并且 偏移的i带类型属性
cout << up6.get()[1].m_x << endl;
}
void test4()
{
unique_ptr<Point>up8 = make_unique<Point>(8);
vector<unique_ptr<Point>>v1;
//v1.push_back(up8);//error 因为 往stl都是拷贝一份,所此处报错,不可以复制
v1.push_back(move(up8));//success
unique_ptr<Point>up9;
//up9 = up8;//error 不支持赋值
up9 = move(up8);//支持移动赋值
unique_ptr<Point>up10(new Point(10));
up10.reset(nullptr);//reset 重置空间 相当于up10指向的原来空间释放,现在指向了nullptr
v1.push_back(unique_ptr<Point>(new Point(777))); // 现在的push_back 传入右值 会直接调用emplace_back
system("pause");
}
void test5()
{
unique_ptr<Point> up11 = make_unique<Point>(11);
//up11.reset(nullptr);
//up11 = nullptr;//2者都会主动释放空间
Point *p11 = up11.release();// 注意与reset的区别 reset是销毁原来的对象,指向新对象,release是释放所有权(与get也有区别 )
printf("up11: %p\n", up11.get());
delete p11;
system("pause");
}
struct Foo
{
Foo() { cout << "Foo constructor" << endl; }
~Foo() { cout << "Foo destructor " << endl; }
char *pData = nullptr;
};
struct D
{
void bar() { cout << "call delete D::bar()" << endl; }
void operator() (Foo *p) {
cout << "call delete Foo object" << endl;
delete p->pData;
delete p;
}
};
void test6()
{
//unique_ptr<Foo, D> up12(new Foo(), D());//出作用域会自动调用 删除器D()
unique_ptr<Foo, D>up13(new Foo(), D()); //同样可以手动 释放
//up13.get_deleter().bar();//类型于匿名对象一样
D& d = up13.get_deleter();//返回的是一个 删除器对象 功能同上
d.bar();
//同样可以自己提前释放
d(up13.get());
up13.release();
system("pause");
}
void test()
{
Point p(999);
vector<Point>v;
// v.reserve(10); //如果预先分配了 空间 拷贝构造就会少执行
cout << v.capacity() << endl;
v.push_back(p);
v.push_back(p);
}
int main()
{
test1(); //先创建指针,再去托管
cout << "after test1" << endl;
test2(); //2种直接托管方式 推荐make_unique
cout << "after test2" << endl;
test3();// 托管对象数组 不过很少这么用,一般用stl+智能指针
cout << "after test3" << endl;
test4();//复制构造 赋值 都被设为delete,但是移动构造和移动赋值可以用
test5();//主动释放
test6();// 删除器释放
test();//stl 测试
system("pause");
}
写了7个大功能测试demo,可根据需求自己注释来详细看 unique_ptr的具体使用功能 推荐结合 cppreferen研究
2.智能指针unique_ptr传参
#include <iostream>
#include <memory>
using namespace std;
void print(const unique_ptr<int[]>& up1)
{
cout << "enter print const" << endl;
for (int i = 0; i < 5; ++i) {
cout << up1[i] << endl;
}
}
void print1(unique_ptr<int[]> up2)
{
cout << "move " << endl;
for (int i = 0; i < 5; ++i) {
cout << up2[i] << endl;
}
}
int main()
{
unique_ptr<int[]> up1 = make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) {
up1[i] = i;
}
print(up1); //传参方式一 推荐使用 因为up不支持复制,而且之后还可以使用
cout << up1[3] << endl;
print1(move(up1));//调用move 但是之后不可再使用
//cout << up1[3] << endl; //error
return 0;
}