C++ 什么是智能指针?

13.1资源(2020.4.6更新) 订购版 简单说明:如果不知道应该下载哪个文件,请阅读本说明。 A.一次性完整下载:选(1) B.分批完整下载:(2)(3)(4)任选 C.独立下载部分文件:(5)到(14)任选 组合文件下载: (1)Quartus II订购版软件(包含芯片) Quartus-13.1.0.162-windows-complete.tar 大小: 10.5 GB MD5: 3593BDDBD185934F1FF98... 阅读详情
 

当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。
 
   智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。
 
   每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
 
   实现引用计数有两种经典策略:一是引入辅助类,二是使用句柄类。下面分别介绍这些内容。

问题描述
 
   假设有一个名为TestPtr的类,里面有一个指针成员,简化为如下代码:

class TestPtr
{
public:
    TestPtr(int *p): ptr(p) { }
    ~TestPtr( ) { delete ptr; }
    // other operations

private:
    int *ptr;
    // other data

};

 
在这种情况下,类TestPtr对象的任何拷贝、赋值操作都会使多个TestPtr对象共享相同的指针。但在一个对象发生析构时,指针指向的对象将被释放,从而可能引起悬垂指针。
 
   现在我们使用引用计数来解决这个问题,一个新的问题是引用计数放在哪里。显然,不能放在TestPtr类中,因为多个对象共享指针时无法同步更新引用计数。
 

方案一
 
   这里给出的解决方案是,定义一个单独的具体类(RefPtr)来封装指针和相应的引用计数。由于这个类只是用于对类TestPtr中的成员指针ptr进行了封装,无其它用途,所以把引用计数类RefPtr的所有成员均定义为private,并把类TestPtr声明为它的友元类,使TestPtr类可以访问RefPtr类。示例代码如下:
 

class RefPtr
{
    friend class TestPtr;
    int *ptr;
    size_t count;
    RefPtr (int *p): ptr(p), count(1) {}
    ~RefPtr () {
        delete ptr;
    }
};

class TestPtr
{
public:
    TestPtr(int *p): ptr(new RefPtr(p)) { }
    TestPtr(const TestPtr& src): ptr(src.ptr) {
        ++ptr->count;
    }
    TestPtr& operator= (const TestPtr& rhs) {
        
// self-assigning is also right
        ++rhs.ptr->count;
        if (--ptr->count == 0)
            delete ptr;
        ptr = rhs.ptr;
        return *this;
    }
    ~TestPtr() {
        if (--ptr->count == 0)
            delete ptr;
    }
private:
    RefPtr *ptr;
};

 
   当希望每个TestPtr对象中的指针所指向的内容改变而不影响其它对象的指针所指向的内容时,可以在发生修改时,创建新的对象,并修改相应的引用计数。这种技术的一个实例就是写时拷贝(Copy-On-Write)。
 
   这种方案的缺点是每个含有指针的类的实现代码中都要自己控制引用计数,比较繁琐。特别是当有多个这类指针时,维护引用计数比较困难。
 

方案二
 
   为了避免上面方案中每个使用指针的类自己去控制引用计数,可以用一个类把指针封装起来。封装好后,这个类对象可以出现在用户类使用指针的任何地方,表现为一个指针的行为。我们可以像指针一样使用它,而不用担心普通成员指针所带来的问题,我们把这样的类叫句柄类。在封装句柄类时,需要申请一个动态分配的引用计数空间,指针与引用计数分开存储。实现示例如下:
 

#include <iostream>
#include <stdexcept>
using namespace std;

#define TEST_SMARTPTR
class Stub
{
public:
    void print() {
        cout<<"Stub: print"<<endl;
    }
    ~Stub(){
        cout<<"Stub: Destructor"<<endl;
    }
};

template <typename T>
class SmartPtr
{
public:
    SmartPtr(T *p = 0): ptr(p), pUse(new size_t(1)) { }
    SmartPtr(const SmartPtr& src): ptr(src.ptr), pUse(src.pUse) {
        ++*pUse;
    }
    SmartPtr& operator= (const SmartPtr& rhs) {
        
// self-assigning is also right
        ++*rhs.pUse;
        decrUse();
        ptr = rhs.ptr;
        pUse = rhs.pUse;
        return *this;
    }
    T *operator->() {
        if (ptr)
            return ptr;
        throw std::runtime_error("access through NULL pointer");
    }
    const T *operator->() const {
        if (ptr)
            return ptr;
        throw std::runtime_error("access through NULL pointer");
    }
    T &operator*() {
        if (ptr)
            return *ptr;
        throw std::runtime_error("dereference of NULL pointer");
    }
    const T &operator*() const {
        if (ptr)
            return *ptr;
        throw std::runtime_error("dereference of NULL pointer");
    }
    ~SmartPtr() {
        decrUse();
#ifdef TEST_SMARTPTR
        std::cout<<"SmartPtr: Destructor"<<std::endl;
// for testing
#endif
    }
    
private:
    void decrUse() {
        if (--*pUse == 0) {
            delete ptr;
            delete pUse;
        }
    }
    T *ptr;
    size_t *pUse;
};

int main()
{
    try {
        SmartPtr<Stub> t;
        t->print();
    } catch (const exception& err) {
        cout<<err.what()<<endl;
    }
    SmartPtr<Stub> t1(new Stub);
    SmartPtr<Stub> t2(t1);
    SmartPtr<Stub> t3(new Stub);
    t3 = t2;
    t1->print();
    (*t3).print();
    
    return 0;
}


 

午餐时间。

zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉。在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养的形象 ——— 或者按照 zero 这些熟悉他本质的人的说法:假象。

“怎么了 zero ?胃口不好么?”,基本填饱肚子之后,Solmyr 觉得似乎应该关心一下他的学徒了。

“呃,没什么,只是 …… Solmyr ,C++ 为什么不支持垃圾收集呢?(注:垃圾收集是一种机制,保证动态分配了的内存块会自动释放,Java 等 语言支持这一机制。)”

Solmyr 叹了口气,用一种平静的眼神盯着 zero :“是不是在 BBS 上和人吵 C++ 和 Java 哪个更好?而且吵输了?我早告诉过你,这种争论再无聊不过了。”

“呃 …… 是”,zero 不得不承认 ——— Solmyr 的眼神虽然一点也不锐利,但是却莫名其妙的让 zero 产生了微微的恐惧感。

“而且,谁告诉你 C++ 不支持垃圾收集的?”

“啊!Solmyr 你不是开玩笑吧?!”

“zero 你得转变一下观念。我问你,C++ 支不支持可以动态改变大小的数组?”

“这 …… 好象也没有吧?”

“那 vector 是什么东西?”

“呃 ……”

“支持一种特性,并不是说非得把这个特性加到语法里去,我们也可以选择用现有的语言机制实现一个库来支持这个特征。以垃圾收集为例,这里我们的任务是要保证每一个被动态分配的内存块都能够被释放,也就是说 ……”,Solmyr 不知从哪里找出了一张纸、一支笔,写到:

int* p = new int; // 1
delete p; // 2

“也就是说,对于每一个 1 ,我们要保证有一个 2 被调用,1 和 2 必须成对出现。我来问你,C++ 中有什么东西是由语言本身保证一定成对出现的?”

“……”,zero 露出了努力搜索记忆的表情,不过很明显一无所获。

“提示一下,和类的创建有关。”

“哦!构造函数与析构函数!”

“正确。可惜普通指针没有构造函数与析构函数,所以我们必须要写一个类来加一层包装,最简单的就象这样:”

class my_intptr
{
public:
int* m_p;

my_intptr(int* p){ m_p = p; }
~my_intptr(){ delete m_p; }
};

…………

my_intptr pi(new int);
*(pi.m_p) = 10;

…………

“这里我们可以放心的使用 my_intptr ,不用担心内存泄漏的问题:一旦 pi 这个变量被销毁,我们知道 pi.p 指向的内存块一定会被释放。不过如果每次使用 my_intptr 都得去访问它的成员未免太麻烦了。为此,可以给这个类加上重载的 * 运算符:”

class my_intptr
{
private:
int* m_p;

public:
my_intptr(int* p){ m_p = p; }
~my_intptr(){ delete m_p; }

int& operator*(){ return *m_p; }
};

…………

my_intptr pi;
*pi = 10;
int a = *pi;

…………

“现在是不是看起来 my_intptr 就像是一个真正的指针了?正因为如此,这种技术被称为智能指针。现在我问你,这个类还缺少哪些东西?”

zero 皱着眉头,眼睛一眨一眨,看上去就像一台慢速电脑正在辛苦的往它的硬盘上拷贝文件。良久,zero 抬起头来,不太确定的说:“是不是还缺少一个拷贝构造函数和一个赋值运算符?”

“说说为什么。”,Solmyr 显然不打算就这样放过 zero。

“因为 …… 我记得没错的话 …… 《50 诫 》(注:指《Effective C++ 2/e》一书)中提到过,如果你的类里面有指针指向动态分配的内存,那么一定要为它写一个拷贝构造函数和一个赋值运算符 …… 因为 …… 否则的话,一旦你做了赋值,会导致两个对象的指针指向同一块内存。对了!如果是上面的类,这样一来会导致同一个指针被 delete 两次!”

“正确。那么我们应该怎样来实现呢?”

“这简单,我们用 memcpy 把目标指针指向的内存中的内容拷贝过来。”

“如果我们的智能指针指向一个类的对象怎么办?注意,类的对象中可能有指针,不能用 memcpy。”

“那 …… 我们用拷贝构造的办法。”

“如果我们的智能指针指向的对象不能拷贝构造怎么办?它可能有一个私有的拷贝构造函数。”

“那 ……”,zero 顿了一顿,决定老实承认,“我不知道。”

“问题在哪你知道么?在于你没有把智能指针看作指针。想象一下,如果我们对一个指针做赋值,它的含义是什么?”

“呃,我明白了,在这种情况下,应该想办法让两个智能指针指向同一个对象 …… 可是 Solmyr ,这样以来岂不是仍然要对同一个对象删除两遍?”

“是的,我们得想办法解决这 个问题,办法不只一种。比较好的一种是为每个指针维护一个引用计数值,每次赋值或者拷贝构造,就让计数值加一,这意味着指向这个内存块的智能指针又多了一 个;而每有一个智能指针被销毁,就让计数值减一,这意味着指向这个内存块的智能指针少了一个;一旦计数值为 0 ,就释放内存块。象这样:”

class my_intptr
{
private:
int* m_p;
int* m_count;

public:
my_intptr(int* p)
{
m_p = p;
m_count = new int; // 初始化计数值为 1
*m_count = 1;
}
my_intptr(const my_intptr& rhs) // 拷贝构造函数
{
m_p = rhs.m_p; // 指向同一块内存
m_count = rhs.m_count; // 使用同一个计数值
(*m_count)++; // 计数值加 1
}
~my_intptr()
{
(*m_count)--; // 计数值减 1
if( *m_count == 0 ) // 已经没有别的指针指向该内存块了
{
delete m_p;
delete m_count;
}
}

my_intptr& operator=(const my_intptr& rhs)
{
if( m_p == rhs.m_p ) // 首先判断是否本来就指向同一内存块
return *this; // 是则直接返回

(*m_count)--; // 计数值减 1 ,因为该指针不再指向原来内存块了
if( *m_count == 0 ) // 已经没有别的指针指向原来内存块了
{
delete m_p;
delete m_count;
}

m_p = rhs.m_p; // 指向同一块内存
m_count = rhs.m_count; // 使用同一个计数值
(*m_count)++; // 计数值加 1
}

…………
};

“其他部分没有什么太大变化,我不费事了。现在想象一下我们怎样使用这种智能指针?”,Solmyr 放下了笔,再次拿起了筷子,有些惋惜的发现他爱吃的肉丸子已经冷了。

zero 想象着,有些迟疑。“我们 …… 可以用 new int 表达式作为构造函数的参数来构造一个智能指针,然后 …… 然后我们可以任意的赋值,”,他开始抓住了思路,越说越快,“任意的用已经存在的智能指针来构造新的智能指针,智能指针的赋值运算符、拷贝构造函数和析构 会保证计数值始终等于指向该内存块的智能指针数。”zero 似乎明白了他看到了怎样的功能, 开始激动起来:“然后一旦计数值为 0 被分配的内存块就会释放!也就是说 …… 有指针指向内存块,它就不释放,一旦没有,它就自动释放!太棒了!我们只要一开始正确的初始化智能指针,就可以象普通指针那样使用它,而且完全不用担心内 存释放的问题!太棒了!”zero 激动的大叫:“这就是垃圾收集!Solmyr !我们在饭桌上实现了一个垃圾收集器!”

Solmyr 很明显没有分享 zero 的激动:“我在吃饭,你能不能不要大叫‘饭桌上实现了一个垃圾收集器’这种倒胃口的话?”顿了一顿,Solmyr 带着他招牌式的坏笑,以一种可恶的口吻说道:“而且请注意一下自己的形象。”

“嗯?”,zero 回过神来,发现自己不知什么时候站了起来,而整个餐厅里的人都在看着他嘿嘿偷笑,这让他感觉自己像个傻瓜。

zero 红着脸坐下,压低了声音问 Solmyr :“不过 Solmyr ,这确实是一个的垃圾收集机制啊,只要我们把这个类改成 …… 嗯 …… 改成模板类,象这样:”zero 抓过了纸笔,写到:

template <typename T>
class my_ptr
{
private:
T* m_p;
int* m_count;
…………
};

“它不就能支持任意类型的指针了吗?我们就可以把它用在任何地方。”

Solmyr 摇了摇头:“不,你把问题想的太简单了。对于简单的类型,这个类确实可以处理的很好,但实际情况是很复杂的。考虑一个典型情况:类 Derived 是类 Base 的派生类,我们希望这样赋值:”

Base* pb;
Derived pd;
…………
pb = pd;

“你倒说说看,这种情况,怎样改用上面这个智能指针来处理?”

“……”,zero 沉默了。

“要实现一个完整的垃圾收集机制并不容易,因为有许多细节要考虑。”,Solmyr 开始总结了,“不过,基本思路就是上面说的这些。值得庆幸的是,目前已经有了一个相当成熟的‘引用计数’智能指针,boost::shared_ptr。 大多数情况下,我们都可以使用它。另外,除了智能指针之外,还有一些技术也能够帮助我们避开释放内存的问题,比如内存池。但是,关键在于 ——— ”

Solmyr 再度用那种平静的眼神盯着 zero :

“身为 C/C++ 程序员,必须有创造力。那种躺在语言机制上不思进取的人,那种必须要靠语法强制才知道怎样编程的人,那种没有别人告诉他该干什么就无所适从的人,不适合这门语言。

引入智能指针可以防止出现悬垂指针的情况
一般是把指针封装到一个称之为智能指针类中,这个类中另外还封装了一个使用计数器,对指针的复制等操作将导致该计数器的值加1,对指针的delete操作则会减1,值为0时,指针为NULL 。

当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。
 
   智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。
 
   每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
 
   实现引用计数有两种经典策略:一是引入辅助类,二是使用句柄类。


下面演示如何使用Boost中的智能指针自动释放悬垂指针和STL中手动释放悬垂指针

 Example: Boost ptr_list:

//The boost ptr_list will perform memory management and "delete" pointers it is containing.
#include <boost/ptr_container/ptr_list.hpp>
#include <iostream>

using namespace std;

class ABC
{
public:
   int i;
   float j;
};

main()
{
   boost::ptr_list<ABC> intList;
   boost::ptr_list<ABC>::iterator iterIntList;

   ABC *a= new ABC;
   ABC *b= new ABC;
   ABC *c= new ABC;

   a->i = 1;
   b->i = 2;
   c->i = 3;

   intList.push_back(a);
   intList.push_back(b);
   intList.push_back(c);

   for (iterIntList = intList.begin();
        iterIntList != intList.end();
        iterIntList++)
   {
      cout << iterIntList->i << endl;
   }

   intList.clear(); // All pointers held in list are deleted.

}

 

  Example: STL list of pointers:
// g++ -g  testStlPtrList.cpp

//This example shows how one must delete each pointer individually.
#include <iostream>
#include <list>

using namespace std;

class ABC
{
public:
   int i;
   float j;
};

main()
{
   list<ABC*> intList;
   list<ABC*>::iterator iterIntList;

   ABC *a= new ABC;
   ABC *b= new ABC;
   ABC *c= new ABC;

   a->i = 1;
   b->i = 2;
   c->i = 3;

   intList.push_back(a);
   intList.push_back(b);
   intList.push_back(c);

   for (iterIntList = intList.begin();
        iterIntList != intList.end();
        iterIntList++)
   {
      cout << (*iterIntList)->i << endl;
   }

   // Free pointers
   for (iterIntList = intList.begin();
        iterIntList != intList.end();
        iterIntList++)
   {
      delete *iterIntList;
   }

   intList.clear(); // List is deleted.

}

 

 VC6中min/max的灾难

 当在VC中使用boost库,或者其他库的时候会有一些小的问题。

在Windows的头文件中已经定义了min 和 max宏,所以在STL中的这两个函数就调用不到了,例如在MFC中就是这样,但是在Boost中,都是使用的std::命名空间下的函数,使用Windows的函数不能够接受不同类型的参数在模板中使用,但是许多库都依赖这些。

虽然Boost尽量处理这些问题,但有时候遇到这样的问题的时候就需要在自己的代码中加入像下面的代码在第一个#include前加入#define _NOMINMAX。

这样操作并不是在任何时候都需要,而只有我们碰到使用了就需要加入这段代码。

Win11多软件报错故障排查:从驱动冲突到系统修复完整指南 Windows系统故障排查是计算机维护的重要环节,其原理在于通过系统日志分析和组件检测定位问题根源。在Win11系统中,驱动兼容性和系统完整性机制尤为关键,这直接影响到软件运行的稳定性。从技术价值看,掌握系统诊断方法能显著提升问题解决效率,避免不必要的数据丢失。特别是在游戏本和多显卡设备场景中,MUX开关导致的显卡驱动冲突是常见问题。本文基于用户反馈的热点问题,通过事件查看器、sfc扫描now等工具,提供从权限调整到驱动更新的全流程解决方案,帮助用户在不重装系统的情况下修复多软件报错问题。 阅读详情

相关推荐

M1 Mac通过UTM虚拟机高效运行Win11的完整指南

本文提供了在M1 Mac上通过UTM虚拟机高效运行Windows 11的完整指南。从获取Windows 11 ARM版镜像到安装配置UTM虚拟机,再到性能优化和常见问题解决,详细介绍了每个步骤。特别适合需要在Mac上运行Windows软件的用户,帮助他们在ARM架构下实现无缝体验。

weixin_30872499的博客 443

C++智能指针

std::unique_ptr可以使用自定义删除器,以支持不同的资源释放策略。通俗的说,有的资源只让unique_ptr自动调用delete或者delete[] 无法完全释放。这时,我们可以自定义释放策略,传给unique_ptr,让其释放资源的时候自动执行。unique_ptr支持传入函数指针和函数对象作为删除器。注意,make_unique不支持自定义删除器的使用,所以。

ymhdt的博客 1121

解码运动想象:BCI Competition IV 2a数据集实战指南

本文提供了BCI Competition IV 2a数据集的实战指南,详细解析了该经典运动想象脑电数据集的结构、文件格式与实验范式。通过MNE-Python等工具,逐步演示了从原始信号读取、预处理(通道选择、滤波、分段)到特征提取(CSP、频带功率)和模型训练(LDA、SVM)的完整流程,并强调了受试者独立评估的重要性,为BCI研究者提供了可复现的入门与进阶路径。

weixin_29304985的博客 362

C++中的智能指针

智能指针是C++标准库提供的类模板,通过封装裸指针实现自动内存管理。其基于RAII机制,在析构时自动释放内存,解决了裸指针的内存泄漏、重复释放和野指针问题。主要分为三种类型:独占型unique_ptr(禁止拷贝,允许移动)、共享型shared_ptr(引用计数)和弱引用weak_ptr(解决循环引用)。智能指针重载*和->运算符,使用方式类似普通指针,但具备类型安全和自动清理特性。相比裸指针,智能指针明确了所有权语义,大幅提升了内存安全性,是现代C++开发中动态内存管理的首选方案。

2301_82190614的博客 536

保姆级教程:用Unity为麒麟系统打包Linux应用(含路径权限全攻略)

本文提供了一份详细的Unity跨平台开发指南,重点介绍如何在麒麟系统上打包和部署Linux应用。从开发环境配置、路径权限处理到性能优化和常见问题解决,全面解析了Unity项目在国产操作系统上的适配流程,帮助开发者高效完成跨平台应用开发。

weixin_28692867的博客 504

用STM32的SPI模式2搞定SSI绝对值编码器通信(附完整代码与避坑点)

本文详细解析了如何使用STM32的SPI模式2实现SSI绝对值编码器通信,包括硬件设计、SPI配置、数据处理算法及稳定性优化技巧。通过完整的代码示例和避坑指南,帮助工程师解决时序匹配、数据解析等常见问题,提升工业自动化系统中的编码器通信可靠性。

weixin_27252001的博客 264

C++智能指针详解

智能指针有多智能?

小白成长之路 1万+

STM32F103 -- LIN从机通讯 -- 程序代码 -- 详细讲解版(2万字长文)

主要代码分为3个文件,usart文件是对GPIO端口和串口Lin模式的初始化,lin_buffer文件是对串口环形缓冲区的编写,lin_driver文件是Lin从机模式驱动代码。通过这三个文件的代码便可实现STM32F103的LIN从机通讯。

晴朗luo的博客 1万+

C++:智能指针

本文介绍了智能指针的概念和原理,以及C++标准库中的auto_ptr、unique_ptr和shared_ptr三种智能指针,分析了shared_ptr中的循环引用问题,并由shared_ptr的循环引用问题出发点,介绍了weak_ptr。

weixin_43908419的博客 8673

YOLOv8 PCB缺陷检测系统全流程实战:从开发到UI展示详解

毕设路上难免有波折,但只要跟着这个教程把“数据集处理、模型训练、UI开发”每一步都落实,你就已经超越了大多数同学。这个“PCB缺陷检测系统”既有技术深度(YOLOv8是工业级主流算法),又有工程价值(解决电子制造的实际痛点),还具备出色的可视化展示——这样的毕设,拿高分是水到渠成的事。

FJN110的博客 214

MCAL中MCU的配置

MCAL配置中MCU配置,PLL计算配置,系统时钟以及各模块参数配置

dhyw12399999的博客 3794

c++智能指针详解

1.什么是智能指针 从比较简单的层面来看,智能指针是RAII(Resource Acquisition Is Initialization,资源获取即初始化)机制对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。 在c++中,智能指针一共定义了4种: auto_ptr、unique_ptr、shared_ptr 和 weak_ptr。其中,auto_ptr 在 C++11已被摒弃,在C++17中已经移除不可用。 2.原始指针的问题 原始指

bitcarmanlee的博客 3万+

paddle 43 用onnxruntime实现ppyoloe模型的部署(含python和c++版本)

PP-YOLOE+是PP-YOLOE模型的升级版,PP-YOLOE+_l在COCO test-dev2017达到了53.3的mAP, 同时其速度在Tesla V100上达到了78.1 FPS。PP-YOLOE+_s/m/x同样具有卓越的精度速度性价比。paddle官方只给出了基于paddle框架的部署案例,为了更好的部署,为此实现将paddle模型转换为onnx模型,然后在python下实现onnxruntime部署。后续会补充c++ onnxruntime部署

a486259的博客 1915

Tiny11Builder完整指南:构建精简版Windows 11镜像,体积直降约60%

Tiny11Builder 是一组开源 PowerShell 脚本,用来自动构建精简版 Windows 11 安装镜像:批量移除数十个预装应用和冗余组件,配合 DISM 恢复压缩,最终 ISO 体积可缩减约六成(约 2.2GB 左右),装进硬盘后的占用也大致减半。全程只用微软自家工具链,一条命令跑完。 ## 常规版与核心版怎么选 仓库里有两个构建脚本:[tiny11maker.ps1](htt

gitblog_01428的博客 1118

线性自抗扰控制(LADRC)系统算法框图

NLADRC自抗扰控制从Simulink仿真到PLC控制实现_自抗扰控制器 simulink仿真-优快云博客本文介绍了如何将ADRC自抗扰控制算法从Simulink仿真应用到PLC控制中,包括Simulink框图、TD微分器模型、MATLAB函数的使用、SCL控制代码,以及非线性状态误差反馈控制率的实现。提供了详细的MATLAB仿真步骤和PLC源代码链接。ADRC自抗扰控制算法(含梯形图完整源代码和算法公式)_adrc算法-优快云博客。

RXXW_Dor的博客 1463

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

诺基亚n900 linux软件,诺基亚N900安装非稳定版MeeGo 1.1详细教程——s60软件

读报、看杂志、看小说,请用手机访问:http://wap.duk.cn8月11日在诺基亚官方博客上,分享了诺基亚N900手机安装非稳定版MegooV1.1版的安装详细教程,希望对N900用户能有所帮助。喜欢折腾的用户现在就可以在诺基亚N900上安装并运行非稳定版的MeeGo1.1系统了。但相对普通用户来说,因为还存在诸多Bug,另外就是安装相对复杂一些,新手用户可以暂等待稍后更新的更完善版本。就在...

weixin_33648177的博客 1109

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

如何快速做出轻量版 Windows 11:tiny11builder 完整指南

tiny11builder 是一套开源 PowerShell 脚本工具,基于微软官方工具链自动精简 Windows 11:DISM(镜像裁剪工具)负责移除预装应用,oscdimg(ISO 烧录工具)负责打包。官方 ISO 进去,tiny11.iso 出来,全程无第三方依赖。 ## 先说结论:它能帮你省掉什么 给老电脑装完 Windows 11 就卡?一大半原因在预装应用:新闻、天气、Xbox、

gitblog_01143的博客 402

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Win11 瘦身 60%:Tiny11Builder 打造轻量系统镜像完整指南

新装的 Win11 动辄 20 多 GB,装完还没怎么用就弹一堆新闻、天气、Xbox;想给十年前的老电脑升级 Win11,又被 TPM 和安全启动卡得死死的。Tiny11Builder 就是来解决这两个问题的:它是一段 PowerShell 脚本,帮你把官方 Windows 11 镜像裁剪、压缩,生成一个更小的轻量 Win11 系统镜像,老机器也能装。 ## 它能帮你瘦掉什么 不用背参数,记住

gitblog_00934的博客 60

终极指南:如何用Tiny11Builder让Windows 11瘦身60%

**Tiny11Builder**是一款强大的开源工具,专门用于构建精简版Windows 11镜像,让你的系统体积减少高达60%!🚀 这个基于PowerShell的脚本能够自动移除Windows 11中不必要的预装应用和组件,同时保持系统的核心功能完整。对于追求极致性能和精简体验的用户来说,Tiny11Builder是完美的解决方案。 ## 什么是Tiny11Builder?🤔 Tiny1

gitblog_00855的博客 1049

如何快速为老旧电脑打造轻量版Windows 11:tiny11builder完整指南

还在为Windows 11的臃肿系统而烦恼吗?老旧电脑运行原版Windows 11卡顿不堪,系统占用空间大、内存消耗高,让很多用户望而却步。今天我要介绍的**tiny11builder**正是解决这一痛点的开源Windows 11精简工具,通过智能脚本帮你打造极致轻量的Windows 11系统镜像,让老旧设备也能流畅运行最新操作系统。 ## Windows 11精简的实用价值 Windows

gitblog_01037的博客 856

朝阳区2025年节能减碳专项资金申报指南

5.对用能单位的能源审计、清洁生产咨询项目,依据评审结果给予不超过15万元奖励,其中市级资金支持的项目,按照市级资金与项目合同总额的差额给予奖励,但不超过市级资金支持额度。实施的节能项目应在本行政区域内。6.对通过国家绿色建筑三星正式标识认证的既有建筑,给予每建筑平方米60元的奖励,对通过国家绿色建筑二星正式标识认证的既有建筑,给予每建筑平方米40元的奖励。8.对通过绿色能源与环境设计先锋奖(LEED)认证铂金奖的建筑,经审核合格后,按照每建筑平方米10元的标准给予奖励,奖励上限不超过200万元。

weixin_44189761的博客 946

用 tiny11builder 打造轻量版 Windows 11:从 28GB 瘦身到 8GB 的完整指南

tiny11builder 是一个开源项目,用 PowerShell 脚本自动构建精简版 Windows 11 安装镜像。它把 Windows 11 装好后的系统体积从 28GB 压到 8~12GB,空闲内存占用从 2.1GB 降到 650MB~850MB,并提供标准、核心两套精简方案,任何语言、任何架构的 Windows 11 版本都能处理。 ## 先做判断:标准版还是核心版 动手之前最值得

gitblog_00228的博客 401

下载 | Win11 26H1官方正式版ISO映像!(6月更新、消费者版/专业版、商业版/企业版、ARM64/x64版、28000.2269)

Win11 26H1 系统ISO映像已放出。提供来自微软官方的26H1消费者版、商业版ISO映像。26H1 版本于2026年初发布,主要面向ARM64的新设备 (比如高通骁龙® X2 系列处理器)。相比25H2版本,没有功能上的更新。

ITHAOGE15的博客 617

如何快速构建精简版Windows 11:tiny11builder完整部署指南

tiny11builder是一款强大的开源工具,能帮助用户快速构建精简版Windows 11镜像,有效减少系统体积并提升运行效率。本指南将详细介绍如何使用tiny11builder构建适合个人需求的精简Windows 11系统,无论是用于老旧电脑提速还是虚拟机环境,都能轻松应对。 ## 🌟 tiny11builder简介 tiny11builder是一套PowerShell脚本集合,专为创建

gitblog_01152的博客 816

如何30分钟创建精简Windows 11系统:tiny11builder完整教程

2. **选择合适的脚本版本**:根据使用场景选择常规版或核心版 3. **准备充足空间**:确保有足够的磁盘空间处理临时文件 4. **耐心等待完成**:整个过程可能需要30-60分钟,取决于硬件性能 5. **测试安装效果**:在虚拟机中先测试生成的ISO文件 通过合理使用tiny11builder,即使是配置较低的设备也能流畅运行Windows 11系统。这个开源工具不仅节省了系统资源,还

gitblog_00854的博客 121

用 Tiny11Builder 精简 Windows 11 的完整制作教程

想给老电脑装 Win11,结果一装完,256GB 的硬盘吃掉一大半,开机还要干等小半分钟。问题多半不在机器,而在系统本体——出厂镜像里塞满了你用不上的应用和服务。Tiny11Builder 就是一个开源的 PowerShell 脚本工具,专门干这件事:把原版 Windows 11 安装镜像中的预装应用、多余服务一次性裁掉,重新打包成体积更小的可安装 ISO。 ## 它裁掉了哪些东西 - 预装应

gitblog_00525的博客 681
上一篇: this指针的用处
下一篇: 类名后加&符号是什么意思?
socketwlazly
博客等级 码龄16年 4粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值