unique_ptr代码练习
unique_ptr代码练习
准备:自定义类cat
cat.h
声明了构造函数析构函数,成员函数cat_info,set_name, get_name:
//"cat.h"
#include<string>
#include<iostream>
#ifndef CLION_PROJ_CAT_H
#define CLION_PROJ_CAT_H
class cat{
public:
cat();
cat(std::string name);
~cat();
void cat_info()const;
void set_name(const std::string name);
std::string get_name() const;
private:
std::string name="miao";
};
#endif //CLION_PROJ_CAT_H
cat.cpp
给出函数定义
//"cat.cpp"
#include "cat.h"
#include <iostream>
using namespace std;
cat::cat(){
cout<<"no params, constructor of cat:"<<name<<endl;
}
cat::cat(std::string name):name(name){
// this->name=name;
cout<<"constructor of cat:"<<name<<endl;
}
cat::~cat(){
cout<<"destructor of cat: "<<name<<endl;
}
void cat::cat_info() const {
cout<<"cat name: "<<name<<endl;
}
std::string cat::get_name() const{
return name;
}
void cat::set_name(const std::string name) {
this->name=name;
}
一、在栈上创建一个cat类型对象
//main.cpp
#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(){
//stack:
cat c1("cat in stack");
c1.cat_info();
{
cat c1("cat in stack inner");
c1.cat_info();
}
cout<<"-----over-----------"<<endl;
return 0;
}
作用域结束自动调用析构函数
constructor of cat:cat in stack
cat name: cat in stack
constructor of cat:cat in stack inner
cat name: cat in stack inner
destructor of cat: cat in stack inner
-----over-----------
destructor of cat: cat in stack
二、堆上创建裸指针
//in "main.cpp"
//heap: raw pointer
cat* c_p1=new cat("cat by raw_ptr");
c_p1->cat_info();//cat name: cat by raw_ptr
int *i_p1=new int(100);
{
int* i_p1=new int(200);//这里是声明了一个新的i_p1,与外部的不是同一个
c_p1=new cat("cat by raw_ptr inner"); //与外部的是同一个
c_p1->cat_info();//cat name: cat by raw_ptr inner
delete c_p1;//destructor of cat: cat by raw_ptr inner
delete i_p1;
}
cout<<*i_p1<<endl; //100,因为200是在局部作用域声明的,
// delete c_p1; //在局部作用域已经delete 不能再delete
delete i_p1;
存在的问题
因为作用域的不同,很容易出错或造成内存泄漏
三、unique_ptr的创建方式
1. 通过已有的裸指针
语法
cat* c_p2 = new cat("by_std::unique_ptr");
std::unique_ptr<cat> u_p1{c_p2};
实例
//create1: std::unique_ptr通过已有的裸指针初始化
cat* c_p2 = new cat("by_std::unique_ptr");
std::unique_ptr<cat> u_p1{c_p2};
u_p1->cat_info();
//test: c_p2还能用吗? 可以
c_p2->set_name("new_name");
c_p2->cat_info(); //new_name
u_p1->cat_info(); //new_name, 创建时使用的裸指针可以修改 u_p1指向的对象
//失去了独占的意义
// 建议销毁原来的 c_p2:
c_p2=nullptr;//必须有这一步
delete c_p2;
u_p1->set_name("nnew");
u_p1->cat_info();//nnew
注意事项:
要把原来的裸指针置空然后销毁,不然就失去了独占的意义。
2. new创建
语法
std::unique_ptr<cat> u_p2 (new cat);//调用无参
std::unique_ptr<cat> u_p3 (new cat());//调用无参
std::unique_ptr<cat> u_p4 (new cat("create2"));//调用含参
实例
//create2: new
std::unique_ptr<cat> u_p2 (new cat);
std::unique_ptr<cat> u_p3 (new cat());
std::unique_ptr<cat> u_p4 (new cat("create2"));
u_p2->cat_info();//默认的 miao
u_p2->set_name("oo");
u_p2->cat_info();//oo
u_p3->cat_info();//默认的 miao
u_p3->set_name("mm");
u_p3->cat_info();//mm
u_p4->cat_info();//create2
u_p4->set_name("nn");
u_p4->cat_info();//nn
3. make_unique 创建
语法
std::unique_ptr <cat> u_p5= make_unique<cat>();
//std::unique_ptr <cat> u_p6= make_unique<cat>; //error
std::unique_ptr <cat> u_p7= make_unique<cat>("ccc");
实例
//create3: make_unique
std::unique_ptr <cat> u_p5= make_unique<cat>();
//std::unique_ptr <cat> u_p6= make_unique<cat>; //error
std::unique_ptr <cat> u_p7= make_unique<cat>("ccc");
u_p5->cat_info();//miao
u_p5->set_name("aa");
u_p5->cat_info();//aa
u_p7->cat_info();//ccc
u_p7->set_name("ddd");
u_p7->cat_info();//ddd
四、get()获取地址与解引用的使用
//get()获取地址
std::unique_ptr<int> i_p1 {new int(100)};
std::unique_ptr<cat> u_p8 {new cat("qaq")};
cout<<"int address: "<<i_p1.get()<<endl; //int address: 0x256dbfc1b40
cout<<"cat address: "<<u_p8.get()<<endl; //cat address: 0x256dbfc1b80
cout<<"deref i_ptr: "<<*i_p1<<endl; //deref i_ptr: 100
std::unique_ptr<int> i_p2= make_unique<int>(200);
std::unique_ptr<cat> u_p9= make_unique<cat>("pp");//constructor of cat:pp
cout<<"int address: "<<i_p2.get()<<endl;//int address: 0x22f46a41b40
cout<<"cat address: "<<u_p9.get()<<endl;//cat address: 0x22f46a41b80
cout<<"deref i_ptr: "<<*i_p2<<endl;//deref i_ptr: 200
参考链接: b站原子之音