独占指针:unique_ptr 与 函数调用 笔记

推荐B站视频:

2.unique_ptr_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV18B4y187uL?p=2&vd_source=a934d7fc6f47698a29dac90a922ba5a3

3.unique_ptr与函数调用_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV18B4y187uL?p=3&vd_source=a934d7fc6f47698a29dac90a922ba5a3一、独占指针:unique_ptr 

  • 任何给定的时刻,只能有一个指针管理内存
  • 当指针超出作用域时,内存将自动释放
  • 该类型指针不可Copy,只可以Move

二、三种创建方式

  • 通过已有裸指针创建
  • 通过new来创建
  • 通过std::make_unique创建(推荐)

准备好头文件和源文件:

  • cat.h
#ifndef CAT_H
#define CAT_H
#include <string>
#include <iostream>
class Cat{
public:
    Cat(std::string name);
    Cat() = default;
    ~Cat();
    void catInfo() const {
        std::cout<<"cat info name : "<<m_name<<std::endl;
    }
    std::string get_name() const{
        return m_name;
    }
    void set_cat_name(const std::string &name) {
        this->m_name = name;
    }
private:
    std::string m_name{"Mimi"};
};
#endif
  • cat.cpp
#include "cat.h"
Cat::Cat(std::string name) :m_name(name) {
    std::cout<<"Constructor of Cat : "<<m_name<<std::endl;
}

Cat::~Cat() {
    std::cout<<"Destructor of Cat"<<std::endl;
}

1.通过已有裸指针创建 

(1)在栈上

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // stack 在main函数下,会在最后一条语句之后再执行析构函数
    Cat c1("maomao");
    c1.catInfo();
    { // 在这个作用域下,结束后会自动销毁
        Cat c1("Tom");
        c1.catInfo();
    }
    cout<<"over~"<<endl; 
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\build> ."D:/Work/C++UserLesson/cppenv/build/app.exe"
Constructor of Cat : maomao
cat info name : maomao
Constructor of Cat : Tom
cat info name : Tom
Destructor of Cat
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\build>

 (2)在堆上

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // roll pointer 原始指针 非常不安全
    Cat* c_p1 = new Cat("Jerry");
    c_p1->catInfo();
    {   
        Cat* c_p1 = new Cat("JiaFeiMao");
        c_p1->catInfo();
    }
    c_p1->catInfo();

    cout<<"over~"<<endl; 
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\build> ."D:/Work/C++UserLesson/cppenv/build/app.exe"
Constructor of Cat : Jerry
cat info name : Jerry
Constructor of Cat : JiaFeiMao
cat info name : JiaFeiMao
cat info name : Jerry
over~
PS D:\Work\C++UserLesson\cppenv\build>
  • 没有执行析构函数,怎么办呢?只能手动释放
#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // roll pointer 原始指针 非常不安全
    Cat* c_p1 = new Cat("Jerry");
    c_p1->catInfo();
    {   
        Cat* c_p1 = new Cat("JiaFeiMao");
        c_p1->catInfo();
        
        // 需要手动释放
        delete c_p1;
        c_p1 = nullptr; // 防止野指针
    }
    c_p1->catInfo();

    // 需要手动释放
    delete c_p1;
    c_p1 = nullptr; // 防止野指针

    cout<<"over~"<<endl; 
    return 0;
}

执行结果: 

PS D:\Work\C++UserLesson\cppenv\build> ."D:/Work/C++UserLesson/cppenv/build/app.exe"
Constructor of Cat : Jerry
cat info name : Jerry
Constructor of Cat : JiaFeiMao
cat info name : JiaFeiMao
Destructor of Cat
cat info name : Jerry
Destructor of Cat
over~
PS D:\Work\C++UserLesson\cppenv\build>

接着再来一个例子:

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // roll pointer 原始指针 非常不安全
    int* i_p1 = new int(100);
    {   
        i_p1 = new int(200);
    }
    cout<<*i_p1<<endl;// 很糟糕,说明没有自动回收该资源
    cout<<"over~"<<endl; 
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
200
over~
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

没有执行析构函数,怎么办呢?只能手动释放

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // roll pointer 原始指针 非常不安全
    int* i_p1 = new int(100);
    {   
        i_p1 = new int(200);
        // 需要手动释放
        delete i_p1;    
        i_p1 = nullptr;
    }
    cout<<"over~"<<endl; 
    return 0;
}

但手动释放的时候,还再多释放一次或者再访问会崩溃

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // roll pointer 原始指针 非常不安全
    int* i_p1 = new int(100);
    {   
        i_p1 = new int(200);
        // 需要手动释放
        delete i_p1;    
        i_p1 = nullptr;
    }
    cout<<*i_p1<<endl;
    // 需要手动释放
    delete i_p1;    
    i_p1 = nullptr;
    cout<<"over~"<<endl; 
    return 0;
}

总结:roll pointer 原始指针 非常不安全

2.通过new来创建

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

int main(int argc,char* argv[]) {
    // unique_point  
    Cat* c_p2 = new Cat("ruite");
    std::unique_ptr<Cat> u_c_p2(c_p2);
    // c_p2还能用吗?
    // 否则如下:无法独占
    c_p2->catInfo();                 //ruite
    u_c_p2->catInfo();               //ruite
    c_p2->set_cat_name("lanmao");
    u_c_p2->catInfo();               //lanmao

    cout<<"over~"<<endl; 
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : ruite
cat info name : ruite
cat info name : ruite
cat info name : lanmao
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

解决无法独占的问题:

  • 方法一:
#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // unique_point  
    Cat* c_p2 = new Cat("ruite");
    std::unique_ptr<Cat> u_c_p2(c_p2);
    c_p2 = nullptr;
    u_c_p2->catInfo();

    cout<<"over~"<<endl; 
    return 0;
}

执行结果: 

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : ruite
cat info name : ruite
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>
  • 方法二:
#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // 第二种 new
    std::unique_ptr<Cat> u_c_p3{new Cat("hongmao")};
    u_c_p3->catInfo();
    u_c_p3->set_cat_name("heimao");
    u_c_p3->catInfo();
    cout<<"over~"<<endl; 
    return 0;
}

执行结果:  

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : hongmao
cat info name : hongmao
cat info name : heimao
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

 3.通过std::make_unique创建(推荐)

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // 推荐创建方式 第三种 std::move_unique
    std::unique_ptr<Cat> u_c_p4 = make_unique<Cat>();
    u_c_p4->catInfo();
    u_c_p4->set_cat_name("huangmao");
    u_c_p4->catInfo();
    cout<<"over~"<<endl; 
    return 0;
}

执行结果:  

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
cat info name : Mimi
cat info name : huangmao
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

三、get()与->和解引用

- unique_ptr可以通过get()获取地址
- unique_ptr实现了->与*
    - 可以调用->调用成员函数
    - 可以调用*调用 deferencing
#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    // 推荐创建方式 第三种 std::move_unique
    std::unique_ptr<Cat> u_c_p4 = make_unique<Cat>();
    std::unique_ptr<int> u_i_p4 = make_unique<int>(200);
    u_c_p4->catInfo();
    u_c_p4->set_cat_name("huangmao");
    u_c_p4->catInfo();

    cout<<"============================"<<endl;

    cout<<*u_i_p4<<endl;
    cout<<"int address: "<<u_i_p4.get()<<endl;
    cout<<"Cat address: "<<u_c_p4.get()<<endl;
    cout<<"over~"<<endl; 
    return 0;
}

执行结果:   

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
cat info name : Mimi
cat info name : huangmao
============================
200
int address: 00000257966B71C0
Cat address: 00000257966C3450
over~
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

四、unique_ptr 与函数调用

第三节:unique_ptr与函数调用
    - unique_ptr是不可Copy,只可以Move
    - 在做函数参数或返回值中一定要注意所有权

函数调用与unique_ptr注意事项
    - Passing by value
        - 需要用std::move来转移内存拥有权
        - 如果参数直接传入std::make_unique语句,自动转换为move
    - Passing by reference
        - 如果设置参数为const则不能改变指向
            - 比如说reset()
        - reset()方法为智能指针清空方法
    - Return by value
        - 指向一个local object
        - 可以用作链式函数

1.pass by value

(1)需要用std::move来转移内存拥有权

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_value(std::unique_ptr<Cat> c) {
    c->catInfo();
} 

int main(int argc,char* argv[]) {
    // 1.pass by value
    std::unique_ptr<Cat> c1 = make_unique<Cat>("Tom");
    do_with_cat_pass_value(std::move(c1));
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : Tom
cat info name : Tom
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

如果在do_with_cat_pass_value(std::move(c1));多加一句:c1->catInfo(); // 此时c1已经无效

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_value(std::unique_ptr<Cat> c) {
    c->catInfo();
} 

int main(int argc,char* argv[]) {
    // 1.pass by value
    std::unique_ptr<Cat> c1 = make_unique<Cat>("Tom");
    do_with_cat_pass_value(std::move(c1));
    c1->catInfo(); // 此时c1已经无效
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : Tom
cat info name : Tom
Destructor of Cat
cat info name :
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

(2)如果参数直接传入std::make_unique语句,自动转换为move

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_value(std::unique_ptr<Cat> c) {
    c->catInfo();
} 

int main(int argc,char* argv[]) {
    do_with_cat_pass_value(make_unique<Cat>("JiaFeiMao")); //move
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : JiaFeiMao
cat info name : JiaFeiMao
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>
  • 总结:如果是pass by value ,传进去以后,这个值就不存在了。它的所有权就转移了,转移到函数里边,函数结束之后就直接消失了 

2.pass by reference

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_ref(std::unique_ptr<Cat>& c) {
    c->set_cat_name("TomCat");
    c->catInfo();
    c.reset();
}

int main(int argc,char* argv[]) {
    // 2. pass by ref
    // (不加const)
    std::unique_ptr<Cat> c2 = make_unique<Cat>("heimao");
    do_with_cat_pass_ref(c2); 
    // c2->catInfo(); // 此时c2已经无效
    cout<<"address: "<<c2.get()<<endl;
    return 0;
}

 运行过程:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : heimao
cat info name : TomCat
Destructor of Cat
address: 0000000000000000
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

 注意:如果do_with_cat_pass_ref函数里不添加c.reset();那么c2->catInfo();还是可以的

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_ref(std::unique_ptr<Cat>& c) {
    c->set_cat_name("TomCat");
    c->catInfo();
    // c.reset();
}

int main(int argc,char* argv[]) {
    // 2. pass by ref
    // (不加const)
    std::unique_ptr<Cat> c2 = make_unique<Cat>("heimao");
    do_with_cat_pass_ref(c2); 
    c2->catInfo(); 
    cout<<"address: "<<c2.get()<<endl;
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : heimao
cat info name : TomCat
cat info name : TomCat
address: 0000018F1CF14640
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

也可以加上const,使得do_with_cat_pass_ref函数内不能使用reset

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

void do_with_cat_pass_ref(const std::unique_ptr<Cat>& c) {
    c->set_cat_name("TomCat");
    c->catInfo();
    // c.reset();// 如果加上了const,无法使用reset()
}

int main(int argc,char* argv[]) {
    // 2. pass by ref
    // (不加const)
    std::unique_ptr<Cat> c2 = make_unique<Cat>("heimao");
    do_with_cat_pass_ref(c2); 
    c2->catInfo(); 
    cout<<"address: "<<c2.get()<<endl;
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : heimao
cat info name : TomCat
cat info name : TomCat
address: 000001D2F5343170
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

 链式调用

#include <iostream>
#include <memory>
#include "cat.h"
using namespace std;

std::unique_ptr<Cat> get_unique_ptr() {
    std::unique_ptr<Cat> p_cat = std::make_unique<Cat>("local cat");
    p_cat->catInfo(); // 输出: local cat
    cout<<p_cat.get()<<endl;
    cout<<&p_cat<<endl;
    p_cat->set_cat_name("TomCat");
    p_cat->catInfo(); // 输出: TomCat
    return p_cat;
}

int main(int argc,char* argv[]) {
    get_unique_ptr()->catInfo();
    cout<<"over~"<<endl;
    return 0;
}

运行结果:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : local cat
cat info name : local cat
0000023AC98439B0
00000077859AF7C8
cat info name : TomCat
cat info name : TomCat
Destructor of Cat
over~
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/350211.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MIT_线性代数笔记:第 29 讲 奇异值分解

目录 如何实现用矩阵数学语言描述这一过程举例 本讲介绍奇异值分解&#xff08;Singular value decomposition&#xff09;&#xff0c;简称 SVD。这是矩阵最终也是最好的分解&#xff0c;任意矩阵可分解为 A U Σ V T AUΣV^T AUΣVT&#xff0c;分解结果为正交矩阵 U&#x…

OpenAI API 的最新动态:新一代的嵌入模型,更新 GPT-4 Turbo,更新 GPT-3.5 Turbo 以及降低 API 价格

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 OpenAI 正在推出新一代嵌入模型、新的 GPT-4 Turbo 和审查模型、新的 API 使用管理工具&#xff0c;而且很快就会降低 GPT-3.5 Turbo 的价格。 OpenAI…

【MAC】Multi-Level Monte Carlo Actor-Critic阅读笔记

基本思想&#xff1a; 利用多层次蒙特卡洛方法&#xff08;Multi-Level Monte Carlo&#xff0c;MLMC&#xff09;和Actor-Critic算法&#xff0c;解决平均奖励强化学习中的快速混合问题。 快速混合&#xff1f; 在强化学习中&#xff0c;当我们说一个策略"混合得快"…

3D视觉技术快讯

SparseGS主要解决了3D GS(Gaussian Splatting)与NeRF类似的稀疏视角问题&#xff0c;即当训练输入视角很稀疏时&#xff0c;GS会在训练中过拟合&#xff0c;从而在新视角上的测试结果较差。本论文则是提出使用原有的深度先验以及显式的约束来提升GS在稀疏视角下的表现&#xff…

以太网与PON网络的巅峰对决

在这网络的江湖中&#xff0c;各路江湖豪侠都神色匆忙地往同一个地方赶&#xff0c;豪侠们脸上都充满期待和焦虑&#xff0c;生怕错过了什么。这个地方就是传说中的园区网&#xff0c;因为在那里万众期待已久的以太网与PON网络的巅峰对决“将在今天上演。 一方是以太网大侠&am…

Hive 行列转换

行列转换 列转行 使用 lateral view explode(array|map) 或 lateral view inline(array_struct) 可以将列转换为行。 单列转多行&#xff0c;降维&#xff08;单列数组或键值对&#xff09; 示例1&#xff1a;explode(array(…)) select ..., A from T lateral view exp…

Java-List接口常用方法和遍历方法

List的继承结构 其中&#xff0c;红色为接口&#xff0c;蓝色为实现类 List的四大方法 List的基本操作void add(int index,E e)boolean remove(Object o)E remove(int index)E set(int index,E e)E get(int index)其中注意删除方法有两种&#xff0c;执行的时候主要选择实参…

作者推荐 | 【深入浅出MySQL】「底层原理」探秘缓冲池的核心奥秘,揭示终极洞察

探秘缓冲池的核心奥秘&#xff0c;揭示终极洞察 缓存池BufferPool机制MySQL缓冲池缓冲池缓冲池的问题 缓冲池的原理数据预读程序的局部性原则&#xff08;集中读写原理&#xff09;时间局部性空间局部性 innodb的数据页查询InnoDB的数据页InnoDB缓冲池缓存数据页InnoDB缓存数据…

可解释性AI

方向一&#xff1a;可解释性AI的定义与重要性 1. 什么是可解释人工智能 可解释人工智能&#xff08;Explainable Artificial Intelligence, XAI&#xff09;是指智能体以一种可解释、可理解、人机互动的方式&#xff0c;与人工智能系统的使用者、受影响者、决策者、开发者等&…

牛客网---------[USACO 2016 Jan S]Angry Cows

题目描述 Bessie the cow has designed what she thinks will be the next big hit video game: "Angry Cows". The premise, which she believes is completely original, is that the player shoots cows with a slingshot into a one-dimensional scene consistin…

中仕教育:事业单位考试考什么?

事业单位考试分为两个阶段&#xff0c;分别是笔试和面试&#xff0c;考试科目包括公共科目和专业科目两部分。 公共科目内容是公共基础知识、职业能力测试或申论。一种形式为&#xff1a;公共基础知识职业能力测试或职业能力测试申论。另一种形式为&#xff1a;公共基础申论。…

图像字幕中一些广泛使用的技术

文章目录 R-CNNsRNNsLSTMs and GRUsResNet R-CNNs 在图像识别领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09;不仅可以识别出图像中的物体&#xff0c;还能检测出这些物体的边界框。如果我们使用传统的CNN进行对象检测&#xff0c;一种方法是在图像上覆盖一层栅格&a…

理想架构的Doherty功率放大器理论与仿真

Doherty理论—理想架构的Doherty功率放大器理论与仿真 参考&#xff1a; 三路Doherty设计 01 射频基础知识–基础概念 ADS仿真工程文件链接&#xff1a;理想架构的Doherty功率放大器理论与仿真 目录 Doherty理论---理想架构的Doherty功率放大器理论与仿真0、Doherty架构的作用…

试卷扫描转化word的功能有吗?分享4款工具!

试卷扫描转化word的功能有吗&#xff1f;分享4款工具&#xff01; 随着科技的飞速发展&#xff0c;将试卷扫描并转化为Word文档已经成为我们日常学习和工作的常规需求。但是&#xff0c;市面上的扫描工具众多&#xff0c;如何选择一个既方便又准确的工具呢&#xff1f;本文将为…

JDWP原理分析与漏洞利用

JDWP(Java DEbugger Wire Protocol):即Java调试线协议,是一个为Java调试而设计的通讯交互协议,它定义了调试器和被调试程序之间传递的信息的格式。说白了就是JVM或者类JVM的虚拟机都支持一种协议,通过该协议,Debugger 端可以和 target VM 通信,可以获取目标 VM的包括类…

力扣刷题 第十二 边权重均等查询

现有一棵由 n 个节点组成的无向树&#xff0c;节点按从 0 到 n - 1 编号。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges &#xff0c;其中 edges[i] [ui, vi, wi] 表示树中存在一条位于节点 ui 和节点 vi 之间、权重为 wi 的边。 另给你一个长度为 m 的二维整数数…

windows根据pid查看端口号

一.什么是PID 任务管理器中的PID指的是进程标识符&#xff08;Process Identifier&#xff09;&#xff0c;它用于在操作系统中唯一标识一个进程二.查看JAVA程序的PID jps命令即可三.根据PID查看端口 netstat -ano|findstr pid

QT5.14.2开发的Mysql8.0系统安装部署过程

最近在Windows 11 64位系统下使用QT5.14.2开发了套系统、使用了MYSQL8.0数据库&#xff0c;项目使用mingw-64编译器进行编译&#xff0c;编译完成后使用windeployqt进行发布&#xff0c;并制作安装包&#xff0c;拷贝到工控机Windows10 64位系统上进行安装运行。本文记录下安装…

机器人3D视觉引导半导体塑封上下料

半导体塑封上下料是封装工艺中的重要环节&#xff0c;直接影响到产品的质量和性能。而3D视觉引导技术的引入&#xff0c;使得这一过程更加高效、精准。它不仅提升了生产效率&#xff0c;减少了人工操作的误差&#xff0c;还为半导体封装技术的智能化升级奠定了坚实的基础。 传统…

兄弟HL-2260黑白激光打印机加粉清零方法

兄弟HL-2260是打印机厂商Brother生产的一款黑白激光多功能一体机&#xff0c;兄弟HL-2260打印机是一款高性价比的打印机&#xff0c;广泛应用于办公和家庭的打印设备&#xff0c;它的打印速度快&#xff0c;而且打印效果好。但是&#xff0c;使用久了之后难免会遇到一些问题&am…