C++的门道(一些C++的关键坑)

2023年C/C++Linux服务器开发/后台架构师知识体系整理(持续更新中) C/C++Linux服务器开发/后台架构师知识体系1. 精进基石专栏1.1 数据结构与算法面试必聊的排序与KMP随处可见的红黑树磁盘存储链式的B树与B+树海量数据去重的Hash与布隆过滤器,bitmap图论算法,di jkstra,dfs,bfs,动态规划1.2 设计模式创建型设计模式结构型设计模式行为型设计模式1.3 工程管理手写:Makefile/cmake/configure操作:git/svn与持续集成Linux系统运行时参数命令2. 高性能网络设计专栏2.1 网络编程网络io与select,pol 阅读详情

C++的门门道道

【导语】 C++是一门被广泛使用的系统级编程语言,更是高性能后端标准开发语言;C++虽功能强大,灵活巧妙,但却属于易学难精的专家型语言,不仅新手难以驾驭,就是老司机也容易掉进各种陷阱。 本文结合作者的工作经验和学习心得,对C++语言的一些高级特性,做了简单介绍;对一些常见的误解,做了解释澄清;对比较容易犯错的地方,做了归纳总结;希望借此能增进大家对C++语言了解,减少编程出错,提升工作效率。

【1】我的程序里用了全局变量,但为什么进程正常停止的时候会莫名其妙的core掉

Rule:C++在不同模块(源文件)里定义的全局变量,不保证构造顺序;但保证在同一模块(源文件)里定义的全局变量,按定义的先后顺序构造,按定义的相反次序析构。

我们程序在a.cpp里定义了依次全局变量X和Y;

按照规则:X先构造,Y后构造;进程停止执行的时候,Y先析构,X后析构;但如果X的析构依赖于Y,那么core的事情就有可能发生。

结论:如果全局变量有依赖关系,那么就把它们放在同一个源文件定义,且按正确的顺序定义,确保依赖关系正确,而不是定义在不同源文件;对于系统中的单件,单件依赖也要注意这个问题。

【2】编译器为什么不给局部变量和成员变量做默认初始化

因为效率,C++被设计为系统级的编程语言,效率是优先考虑的方向,c++秉持的一个设计哲学是不为不必要的操作付出任何额外的代价,所以它有别于java,不给成员变量和局部变量做默认初始化,如果需要赋初值,那就由程序员自己去保证。

结论:从安全的角度出发,定义变量的时候赋初值是一个好的习惯,很多错误皆因未正确初始化而起,C++11支持成员变量定义的时候直接初始化,成员变量尽量在成员初始化列表里初始化,且要按定义的顺序初始化。

【3】std::sort()的比较函数有很强的约束,不能乱来啊

相信工作5年以上至少50%的C/C++程序员都被它坑过,我已经听到过了无数个悲伤的故事,《圣斗士星矢》,《仙剑》,还有别人家的项目《天天爱消除》,都有人掉坑,程序运行几天莫名奇妙的Crash掉,这锅好沉。

如果要用,要自己提供比较函数或者函数对象,一定搞清楚什么叫“严格弱排序”,一定要满足以下3个特性:

非自反性

非对称性

传递性

尽量对索引或者指针sort,而不是针对对象本身,因为如果对象比较大,交换(复制)对象比交换指针或索引更耗费。

【4】注意操作符短路

考虑游戏玩家回血回蓝(魔法)刷新给客户端的逻辑。玩家每3秒回一点血,玩家每5秒回一点蓝,回蓝回血共用一个协议通知客户端,也就是说只要有回血或者回蓝就要把新的血量和魔法值通知客户端。

玩家的心跳函数heartbeat()在主逻辑线程被循环调用

void GamePlayer::Heartbeat()
{
if (GenHP() || GenMP())
{
NotifyClientHPMP();
}
}
如果GenHP回血了,就返回true,否则false;不一定每次调用GenHP都会回血,取决于是否达到3秒间隔。

如果GenMP回蓝了,就返回true,否则false;不一定每次调用GenMP都会回血,取决于是否达到5秒间隔。

实际运行发现回血回蓝逻辑不对,Word麻,原来是操作符短路了,如果GenHP()返回true了,那GenMP()就不会被调用,就有可能失去回蓝的机会。OMG,你需要修改程序如下:

void GamePlayer::Heartbeat()
{
bool hp = GenHP();
bool mp = GenMP();
if (hp || mp)
{
NotifyClientHPMP();
}
}
逻辑与(&&)跟逻辑或(||)有同样的问题, if (a && b) 如果a的表达式求值为false,b表达式也不会被计算。

有时候,我们会写出 if (ptr != nullptr && ptr->Do())这样的代码,这正是利用了操作符短路的语法特征。

【5】理解std::vector的底层实现

(a) vector是动态扩容的,2的次方往上翻,为了确保数据保存在连续空间,每次扩充,会将原member悉数拷贝到新的内存块; 不要保存vector内对象的指针,扩容会导致其失效 ;可以通过保存其下标index替代。

(b) 运行过程中需要动态增删的vector,不宜存放大的对象本身 ,因为扩容会导致所有成员拷贝构造,消耗较大,可以通过保存对象指针替代。

©resize()是重置大小;reserve()是预留空间,并未改变size(),可避免多次扩容; clear()并不会导致空间收缩 ,如果需要释放空间,可以跟空的vector交换,std::vector .swap(v),c++11里shrink_to_fit()也能收缩内存。

(d) 理解at()和operator[]的区别 :at()会做下标越界检查,operator[]提供数组索引级的访问,在release版本下不会检查下标,VC会在Debug版本会检查;c++标准规定:operator[]不提供下标安全性检查。

(e)C++标准规定了std::vector的底层用数组实现,认清这一点并利用这一点。

【6】用c标准库的安全版本(带n标识)替换非安全版本,比如用strncpy替代strcpy,用snprintf替代sprintf,用strncat代替strcat,用strncmp代替strcmp,memcpy(dst, src, n)要确保[dst,dst+n]和[src, src+n]都有有效的虚拟内存地址空间。;多线程环境下,要用系统调用或者库函数的安全版本代替非安全版本(_r版本),谨记strtok,gmtime等标准c函数都不是线程安全的

【7】理解函数调用的性能开销(栈帧建立和销毁,参数传递,控制转移),性能敏感函数考虑inline

X86_64体系结构因为通用寄存器数目增加到16个,所以64位系统下参数数目不多的函数调用,将会由寄存器传递代替压栈方式传递参数,但栈帧建立、撤销和控制转移依然会对性能有所影响。

【8】理解user stack空间很有限,不能在栈上定义过大的临时对象,递归函数要有退出条件且不能递归过深

一般而言,用户栈只有几兆(典型大小是4M,8M),所以栈上创建的对象不能太大;虽然递归函数能简化程序编写,但也常常带来运行速度变慢的问题,所以需要预估好递归深度,优先考虑非递归实现版本。

【9】内存拷贝小心内存越界;memcpy,memset有很强的限制,仅能用于POD结构,不能作用于stl容器或者带有虚函数的类

带虚函数的类对象会有一个虚函数表的指针,memcpy将破坏该指针指向。

对非POD执行memset/memcpy,免费送你四个字:自求多福。

【10】用sprintf格式化字符串的时候,类型和格式化符号要严格匹配,因为sprintf的函数实现里是按格式化串从栈上取参数,任何不一致,都有可能引起不可预知的错误; /usr/include/inttypes.h里定义了跨平台的格式化符号,比如PRId64用于格式化int64_t

【11】stl容器的遍历删除要小心迭代器失效,vector,list,map,set等各有不同的写法

#include
#include
#include
#include
#include

int main(int argc, char *argv[])
{
//vector遍历删除
std::vector v(8);
std::generate(v.begin(), v.end(), std::rand);
std::cout << “after vector generate…\n”;
std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, “\n”));

for (auto x = v.begin(); x != v.end(); )
{
    if (*x % 2)
        x = v.erase(x);
    else
        ++x;
}

std::cout << "after vector erase...\n";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, "\n"));

//map遍历删除
std::map<int, int> m = {{1,2}, {8,4}, {5,6}, {6,7}};

for (auto x = m.begin(); x != m.end(); )
{
    if (x->first % 2)
        m.erase(x++);
    else
        ++x;
}

return 0;

}
有时候遍历删除的逻辑不是这么明显,可能循环里调了另一个函数,而该函数在某种特定的情况下才会删除当前元素,这样的话,就是很长一段时间,程序都运行得好好的,而当你正跟别人谈笑风生的时候,忽然crash,这就尴尬了。

圣斗士星矢项目曾经遭遇过这个问题,基本规律是一个礼拜game server crash一次,折磨团队将近一个月。

比较low的处理方式可以把待删元素放到另一个容器WaitEraseContainer里保存下来,再走一趟单独的循环,删除待删元素。

当然,我们推荐在遍历的同时删除,因为这样效率更高,也显得行家里手。

【12】积极的使用const,理解const不仅仅是一种语法层面的保护机制,也会影响程序的编译和运行

const常量会被编码到机器指令。

【13】理解四种转型的含义和区别,避免用错,尽量少用向下转型(可以通过设计加以改进)

static_cast, dynamic_cast,const_cast,reinterpret_cast,傻傻分不清?

C++砖家说:一句话,尽量少用转型,强制类型转换是C Style,如果你的C++代码需要类型强转,你需要去考虑是否设计有问题。不管您信不信,我反正是信了。

【14】打开的句柄要关闭,加锁/解锁,new/delete,new[]/delete[],malloc/free要配对,可以使用RAII技术防止资源泄露,编写符合规范的代码

Valgrind对程序的内存使用方式有期望,需要干净的释放,所以规范编程才能写出valgrind干净的代码,不然再好的工具碰到不按规划写的代码也是武功尽废啊。

【15】理解多继承潜在的问题,慎用多继承

多继承会存在菱形继承的问题,多个基类有相同成员变量会有问题,需要谨慎对待。

【16】有多态用法抽象基类的析构函数要加virtual关键字

主要是为了基类的析构函数能得到正确的调用。

virtual dtor跟普通虚函数一样,基类指针指向子类对象的时候,delete ptr,根据虚函数特征,如果析构函数是普通函数,那么就调用ptr显式(基类)类型的析构函数;如果析构函数是virtual,则会调用子类的析构函数,然后再调用基类析构函数。

【17】避免在构造函数和析构函数里调用虚函数

构造函数里,对象并没有完全构建好,此时调用虚函数不一定能正确绑定,析构亦如此。

【18】从输入流获取数据,要做好数据不够的处理,要加try catch;没有被吞咽的exception,会被传播

从网络数据流读取数据,从数据库恢复数据都需要注意这个问题。

【19】协议尽量不要传float,如果传float要了解NaN的概念,要做好检查,避免恶意传播

【20】定义宏要遵循常规,要对每个变量加括弧,有时候需要加do {} while(0)或者{},以便能将一条宏当成一个语句。要理解宏在预处理阶段被替换,不用的时候要#undef,要防止污染别人的代码

【21】了解智能指针,理解基于引用计数法的智能指针实现方式,了解所有权转移的概念,理解shared_ptr和unique_ptr的区别和适用场景

考虑用std::shared_ptr管理动态分配的对象。

【22】了解c++高阶特性:模板和泛型编程,union,bitfield,指向成员的指针,placement new,显式析构,异常机制,nested class,local class,namespace,多继承、虚继承,volatile,extern "C"等

有些高级特性只有在特定情况下才会被用到,但技多不压身,平时还是需要积累和了解,这样在需求出现时,才能从自己的知识库里拿出工具来对付它。

【23】了解C++新标准,关注新技术,c++11/14/17、lambda,右值引用,move语义,多线程库等

c++98/03标准到c++11标准的推出历经13年,13年来程序设计语言的思想得到了很大的发展,c++11新标准吸收了很多其他语言的新特性,虽然c++11新标准主要是靠引入新的库来支持新特征,核心语言的变化较少,但新标准还是引入了move语义等核心语法层面的修改,每个CPPer都应该了解新标准。

【24】OOP设计原则并不是胡扯

设计模式六大原则(1):单一职责原则

设计模式六大原则(2):里氏替换原则

设计模式六大原则(3):依赖倒置原则

设计模式六大原则(4):接口隔离原则

设计模式六大原则(5):迪米特法则

设计模式六大原则(6):开闭原则

【25】熟悉常用设计模式,活学活用,不生搬硬套

神化设计模式和反设计模式,都不是科学的态度,设计模式是软件设计的经验总结,有一定的价值;GOF书上对每一个设计模式,都用专门的段落讲它的应用场景和适用性,限制和缺陷,在正确评估得失的情况下,是鼓励使用的,但显然,你首先需要准确get到她。

【26】了解延迟计算、COW和分散计算

比如游戏服务器端玩家的战力,由属性a,b决定,也就是说属性a,b任何一个变化,都需要重算战力;但如果ModifyPropertyA(),ModifyPropertyB()之后,都重算战力却并非真正必要,因为修改属性A之后有可能马上修改B,两次重算战力,显然第一次重算的结果会很快被第二次的重算覆盖。

而且很多情况下,我们可能需要在心跳里,把最新的战力值推送给客户端,这样的话,ModifyPropertyA(),ModifyPropertyB()里,我们其实只需要把战力置脏,延迟计算,这样就能避免不必要的计算。

在GetFightValue()里判断FightValueDirtyFlag,如果脏,则重算,清脏标记;如果不脏,直接返回之前计算的结果。

分散计算是把任务分散,打碎,避免一次大计算量,卡住程序。

延迟计算和分散计算都是常见的套路。

【27】理解字节对齐

自己对齐能让存储器访问速度更快。
自己对齐跟cpu架构相关,有些cpu访问特定类型的数据必须在一定地址对齐的储存器位置,否则会触发异常。

字节对齐的另一个影响是调整结构体成员变量的定义顺序,有可能减少结构体大小,这在某些情况下,能节省内存。

【28】牢记3 rules和5 rules,当然C++11又多了&&的copy ctor和op=版本

只在需要接管的时候才自定义operator=和copy constructor,如果编译器提供的默认版本工作的很好,不要去自找麻烦,自定义的版本勿忘拷贝每一个成分,如果要接管就要处理好。

【29】组合优先于继承,继承是一种最强的类间关系

【30】减少依赖,注意隔离

最大限度的减少文件间的依赖关系,用前向声明拆解相互依赖。

了解pimpl技术。

头文件要自给自足,不要包含不必要的头文件,也不要把该包含的头文件推给user去包含,一句话,头文件包含要不多不少刚刚好。

【31】别让循环停不下来

for (unsigned int i = 5; i >=0; --i)
{
…
}
程序跑到这,纳尼?根本停不下来啊?问题很简单,unsigned永远>=0,是不是心中一万只马奔腾?

解决这个问题很简单,但是有时候这一类的错误却没这么明显,你需要罩子放亮点,多个心眼。

【32】size_t到底是个什么鬼?我该用有符号还是无符号整数?

size_t类型是被设计来保存系统存储器上能保存的对象的最大个数。

32位系统,一个对象最小的单位是一个字节,那2的32次方内存,最多能保存的对象数目就是4G/1字节,正好一个unsigned int能保存下来(typedef unsigned int size_t)。

同样,64位系统,unsigned long是8字节,所以size_t就是unsigned long的类型别名。

对于像索引,位置这样的变量,是用有符号还是无符号呢?像money这样的属性呢?

一句话:要讲道理,用最自然,最顺理成章的类型。比如索引不可能为负用size_t,账户可能欠钱,则money用int。

比如

template class vector
{
T& operator(size_t index) {}
};
标准库给出了最好的示范,因为如果是有符号的话,你需要这样判断

if (index < 0 || index >= max_num) throw out_of_bound();

而如果是无符号整数,你只需要判断 if (index >= max_num),你认可吗?

【33】对于在启动时加载好,运行中不变化的查询结构,可以考虑用sorted array替代map,hash表等

因为有序数组支持二分查找,效率跟map差不多。对于只需要在程序启动的时候构建(排序)一次的查询结构,有序数组相比map和hash可能有更好的内存命中性(局部命中性)。

运行过程中,稳定的查询结构(比如配置表,需要根据id查找配置表项,运行过程中不增删),有序数组是个不错的选择;如果不稳定,则有序数组的插入删除效率比map,hashtable差,所以选用有序数组需要注意适用场合。

【34】std::map还是std::unorder_map,我真的很纠结

想清楚他们的利弊,map是用红黑树做的,unorder_map底层是hash表做的,hash表相对于红黑树有更高的查找性能。hash表的效率取决于hash算法和冲突解决方法(一般是拉链法,hash桶),以及数据分布,如果负载因子高,就会降低命中率,为了提高命中率,就需要扩容,重新hash,而重新hash是很慢的,相当于卡一下。

而红黑树有更好的平均复杂度,所以如果数据量不是特别大,map是胜任的。

【35】整型一般用int,long就很好,用short,char需要很仔细,要防止溢出

大多数情况下,用int,long就很好,long一般等于机器字长,long能直接放到寄存器,硬件处理起来速度也更快。

很多时候,我们希望用short,char达到减少结构体大小的目的。但是由于字节对齐,可能并不能真正减少,而且1,2个字节的整型位数太少,一不小心就溢出了,需要特别注意。

所以,除非在db、网络这些对存储大小非常敏感的场合,我们才需要考虑是否以short,char替代int,long。

UE5.5Pico VR 入门关键坑 插件时,无法编译通过,需要先确保CPP支持,然后从新生成VS解决方案,进VS编译后,才能正常使用.,这是控制器的真实名称,如果还不对就打印下日志看下,再修改.中拷贝源码到上面创建的文件夹,可编译通过。来调整模型手和手柄定位的相对位置等.函数,其中对比控制器命名的地方改为。 阅读详情

相关推荐

麒麟V10服务器离线部署llama.cpp+Hermes AI助手实战指南

大语言模型作为人工智能的核心技术,通过Transformer架构实现文本理解和生成能力。其原理基于自注意力机制,能够捕捉长距离依赖关系。在工程实践中,CPU推理技术让大模型在资源受限环境中部署成为可能,特别是llama.cpp框架通过量化优化显著降低内存占用。这种技术方案在金融、政务等对数据安全要求高的离线场景中价值凸显,能够实现本地文档处理、知识问答等企业级应用。本文基于麒麟V10国产化平台,详细解析llama.cpp与Hermes Agent框架的集成部署,重点解决ARM架构编译优化、内存资源限制等实际

迷彩风情 441

c++架构师需要掌握哪些知识

本文技术梳理主要针对于三类人群的技术需求 1.即将毕业的本科,研究生计算机科班应届生; 2.有c/c++语言基础,工作1-3年还在开发岗位寻找技术方向定位的在职工程师; 3.已经在c/c++下从事多年其他方向的技术开发,有准备往服务器开发方向尝试的工程师。...

技术Q君样:202432010的博客 3915

C++集成AI大模型实战:性能优化与生产部署指南

AI模型集成是当前软件开发的重要趋势,特别是在需要高性能和低延迟的场景中。C++作为系统级编程语言,其性能优势使其成为金融交易、自动驾驶等关键领域的首选。通过ONNX Runtime等跨平台推理引擎,开发者可以在保持C++性能的同时集成先进的AI能力。本文深入探讨了模型转换、接口封装、内存优化和批处理等核心技术,并分享了生产环境中容器化部署和性能监控的实战经验。对于需要处理高并发、低延迟场景的开发者,这些技术能显著提升系统吞吐量和稳定性。

weixin_29029995的博客 338

为全局变量赋值_关于多线程使用全局变量的问题

在多线程中,如果多线程同时对一个全局变量进行操作时,就有可能出现异常,比如下面的程序:# -*- coding:UTF-8 -*-import threadingimport time#定义一个全局变量g_num = 0def test1(num): global g_num for i in range(num): g_num += 1 print(g_...

weixin_39743824的博客 1712

C/C++日期算法实战:从闰年判断到蔡勒公式的完整解析

日期时间处理是编程中的基础但易错环节,涉及公历规则建模与边界条件把控。其核心原理基于格里高利历的闰年规则(四年一闰、百年不闰、四百年再闰)和月份天数的不规律性。掌握这些底层算法不仅有助于理解时间计算的本质,在嵌入式开发、历史数据处理等特殊场景及技术面试中更具实用价值。通过实现日期差计算、星期几判断等经典问题,开发者能锻炼综合运用基础知识和防御性编程的能力。本文深入探讨了**蔡勒公式**的应用与**日期合法性校验**等关键点,为C/C++工程师提供了一套解决日期相关问题的通用思维框架与调试技巧。

weixin_31364787的博客 221

C++ 结合 ONNXruntime 实现高效模型部署与 TensorRT 加速实战

本文详细介绍了使用C++结合ONNXruntime实现高效深度学习模型部署的完整流程,并重点讲解了如何集成TensorRT进行极致加速。内容涵盖从模型转换、环境搭建、C++核心API使用到性能优化与避坑指南,旨在帮助开发者将训练好的模型高效、稳定地部署到边缘设备等生产环境中。

weixin_29061425的博客 391

c++程序常见core处理--2020-09-07

首先遇到core文件,一般会采用gdb+进程执行命令+core名称(遇到core文件带单引号的可以用\转义下)。 定位到core的代码行数,一般分两种情况: 1、代码是自己业务代码行。 这种情况下一般情况比较容易解决,大部分为: 1、对空指针操作;不管别的模块是否判断指针,对指针操作前一定要先判空。 2、数组溢出;要注意取值范围,常见的是字符串的问题。 3、类析构时出现;当进程是通过调用共享库编译出的库时,如果某个库...

shihuangdeng898的博客 1516

从MFC到现代C++17:游戏服务器跨平台重构实战与架构演进

在现代软件开发中,服务器架构的演进是提升系统性能和可维护性的关键。从传统的单体架构到现代的异步事件驱动模型,技术栈的升级往往涉及核心设计理念的转变。以C++为例,从早期的MFC框架迁移到现代C++17标准,不仅是语法层面的更新,更是对内存安全、并发模型和跨平台能力的系统性重构。这种重构的技术价值在于能够显著提升服务器的并发处理能力、降低资源消耗,并实现Linux与Windows环境的无缝部署。在实际应用场景中,游戏服务器尤其需要高性能的网络通信和稳定的服务运行,因此采用Boost.Asio等异步I/O库结合

weixin_33889245的博客 481

多线程中全局结构体变量,string赋值引起core

定义线程传参结构体如下: struct ThreadPara { std::string strNeName; string strTime; bool IsSuccess; std::string strNeInst; ThreadPara():strNeName(""),strTime(""),IsSuccess(false),strDesc(""),...

qq_39268442的博客 1477

C++加密开发实战:Crypto++静态库配置与集成全攻略

在C++项目开发中,加密功能是保障数据安全的核心需求,涉及网络通信、文件保护与数据签名等多个关键场景。其实现原理通常依赖于成熟稳定的加密算法库,通过静态或动态链接的方式集成到应用程序中。从技术价值看,选择合适的加密库并正确配置,能显著提升项目的安全性与可维护性,避免因环境依赖问题导致的部署失败。本文聚焦于广泛使用的Crypto++库,针对其**静态链接**的集成方式,详细解析了在**Visual Studio**、CMake及GCC/Clang等不同开发环境下的配置步骤与常见问题解决方案,旨在帮助开发者快速

weixin_34357887的博客 468

AMD显卡跑MiniMax H3提速30%:SageAttention ROCm适配全记录

在Transformer架构的视频生成模型中,注意力计算往往是性能瓶颈,尤其当显存资源受限时,低精度量化与内核优化成为关键突破口。SageAttention通过将QK^T矩阵乘法量化为INT8,并以FP16/INT4表达注意力概率矩阵,在保证画质的前提下显著降低访存与计算开销,相比传统FlashAttention具备更高速度上限。这一技术价值在本地部署场景尤为突出——当用户使用非NVIDIA显卡运行大型视频模型时,通用优化库常因依赖CUDA而失效。本文聚焦AMD ROCm平台下的MiniMax H3视频生成

weixin_32238157的博客 270

C++数位 DP解析

本文以对话形式深入解析数位DP算法,从原理到实战逐步拆解。数位DP是动态规划中专门处理数字统计问题的经典方法,适用于大数范围(如1e18)下统计满足特定数位条件的数字数量。文章通过两个典型例题(统计不含数字6的数和各位数字之和等于sum的数)详细讲解四步核心框架:数字拆分、递归函数设计、记忆化搜索和区间处理。代码实现清晰展示了状态定义、边界条件处理和记忆化优化技巧,帮助读者彻底掌握这一高效算法。

互联网改遍了世界。 596

如何在软件复位后保留指定RAM区域的数据

本文主要介绍S32K144的RAM retention功能

北极熊的脖子(16605192620@163.com) 1万+

C++ map & set 实用全解:从基础用法到算法题优化,一篇搞定

map 和 set 是 STL 中最实用的关联容器

mogreat的博客 768

基于FMCW技术的毫米波雷达测速原理与应用

调频连续波(FMCW)技术是毫米波雷达中实现高精度测速的核心方法之一。本文详细介绍了FMCW测速的基本原理、信号处理流程以及在实际应用中的关键技术。通过分析FMCW雷达的多普勒效应和频率差测量方法,本文展示了如何利用FMCW技术实现目标速度的高精度检测。此外,本文还探讨了FMCW测速在自动驾驶、智能交通和工业自动化等领域的应用案例,为毫米波雷达开发者提供了理论支持和实践指导。

不谈枯燥公式,只聊雷达趋势。用大白话解读毫米波里的黑科技。 1136

【深度强化学习】(2) Double DQN 模型解析,附Pytorch完整代码

Double DQN 算法是 DQN 算法的改进版本,解决了 DQN 算法过估计行为价值的问题。Double DQN 算法不直接通过最大化的方式选取目标网络计算的所有可能 Q 值,而是首先通过估计网络选取最大 Q 值对应的动作。在 Double DQN 框架中存在两个神经网络模型,分别是训练网络与目标网络。这两个神经网络模型的结构完全相同,但是权重参数不同;每训练一段之间后,训练网络的权重参数才会复制给目标网络。

博观而约取,厚积而薄发 1万+

Windows下PaddleOCR C++编译避坑指南:从环境配置到成功运行的全流程

本文详细解析了在Windows系统下编译PaddleOCR C++版本的完整流程与关键避坑点。内容涵盖从Visual Studio、CMake、OpenCV等环境配置,到CMake项目生成、Visual Studio编译链接,再到运行时依赖处理与中文乱码解决的全过程,旨在帮助开发者高效完成编译部署,避免常见错误。

corn8的博客 192

21天教你学会PCIe专栏(14)--安全性考虑

1.1 定义安全性(Security):安全性是指保护系统免受未经授权的访问、攻击和破坏,确保数据的机密性、完整性和可用性。1.2 重要性数据保护:保护敏感数据,防止数据泄露和篡改。系统防护:防止恶意攻击,确保系统的稳定性和可靠性。合规性:满足行业标准和法律法规的要求,避免法律风险。用户信任:提高用户对系统的信任度,增强市场竞争力。通过今天的学习,你应该对PCIe安全性的重要性和常见威胁有了深入的了解,掌握了实施安全措施的方法和工具,以及安全开发的最佳实践。

xiaoheshang_123的博客 850

C++ OpenCV 使用 yolov8 onnx 的详细代码记录

再次训练并部署yolov8模型

learner_jj的博客 228

yolov26改进 | Neck/颈部创新篇 | 独创HFPN利用分层特征融合块HFFB模块融合多层次特征改进yolov26(全网独家创新)

本文提出了一种创新的分层特征融合模块HFFB(Hierarchical Feature Fusion Block)来改进YOLOv26的neck部分,构建了名为HFPN的新型特征金字塔网络。该模块通过三分支结构融合局部特征(CNN提取)、全局特征(Swin Transformer提取)和中间特征,并包含空间注意力(SA)、通道注意力(CA)和残差反向MLP(IRMLP)等组件来优化特征融合效果。实验表明,该方法能针对不同尺度目标(大/中/小)进行自适应检测,可根据具体数据集需求选择不同配置。文章详细提供了核

Snu77的博客 483

【ROS】ROS2导航Nav2:简介、安装、测试效果、错误处理

在ROS2中自动导航使用Nav2来实现。Nav2 使用几个独立的模块化服务,通过 ROS 2接口(例如动作服务器或服务)与行为树 (BT) 通信。Nav2 输入包括:TF转换、一个地图源、一个行为树 (BT) XML 文件和相关的传感器数据源;Nav2 输出速度命令;Nav2 支持多种机器人,比如:四足机器人、履带机器人、轮式机器人等。

郭老二 5078

C++ 继承:构造析构 的细节

知识点核心规则常见坑点子类构造 / 拷贝构造构造先父后子,拷贝构造先切片父类;自定义构造必须初始化父类构造忘记在初始化列表调用父类有参构造子类析构析构先子后父,自动调用父类析构;多态场景父类析构必须设为 virtual父类析构不加 virtual 导致子类内存泄漏。

m0_73919066的博客 1149

PINN:当深度学习遇上朗伯-比尔定律

光谱数据处理中引入PINN的三种架构设计

qq_53529450的博客 154

C++ STL 队列(queue)从入门到进阶:一篇搞懂

先来的人先买到,后来的人排后面。队列(Queue)就是这样一种数据结构,遵循FIFO(First In First Out,先进先出)入队(push):新元素只能从队尾加入,就像排在队伍最后面。出队(pop):元素只能从队首离开,就像排在队伍最前面的人先买到奶茶。在 C++ 中,使用队列只需引入一个头文件:// 使用 queue 必须包含的头文件💡记住这张对比图栈(Stack):后进先出(LIFO),像一摞盘子,只能从顶部取放。队列(Queue):先进先出(FIFO),像排队,队尾进、队首出。

2301_80018451的博客 247

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Hunyuan-MT-7B在C++项目中的集成与应用

本文介绍了如何在星图GPU平台上自动化部署Hunyuan-MT-7B镜像,实现低延迟、高确定性的多语种机器翻译。通过C++原生集成,该镜像可高效应用于实时字幕生成、嵌入式设备告警翻译等对响应速度和资源占用敏感的工业场景,显著提升AI落地性能与稳定性。

weixin_35761094的博客 395

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C++默认六大默认函数

C++默认成员函数概述 在C++中,当一个类没有显式定义某些成员函数时,编译器会自动生成默认版本。C++11标准后,一个空类默认会生成6个成员函数: 默认构造函数 析构函数 拷贝构造函数 拷贝赋值运算符 移动构造函数(C++11新增) 移动赋值运算符(C++11新增) 这些默认函数的行为各有特点: 构造函数和析构函数负责对象的创建和销毁 拷贝操作默认执行浅拷贝 移动操作通过"窃取"临时对象资源提高效率 特别注意: 显式定义某些函数会影响其他默认函数的生成 包含指针成员的类需要手动实现深拷

doubleintfloat的博客 621

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

上一篇: HTTP协议格式详解
下一篇: 升级https总结
山农
博客等级 码龄10年 44粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值