自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(40)
  • 收藏
  • 关注

原创 C++类和对象的基本概念:封装、定义、设计与实现

展示了如何设计一个类。cout << "名字:" << obj.getName() << ",年龄:" << obj.getAge() << endl;cout << "名字:" << obj.getName() << ",年龄:" << obj.getAge() << endl;cout << "名字:" << obj.getName() << ",年龄:" << obj.getAge() << endl;cout << "名字:" << mName << ",年龄:" << mAge << endl;

2024-07-15 17:05:02 546

原创 C++反射的实现方式

在C++中,反射(reflection)通常是指在运行时检查或修改程序结构的能力,比如类型、对象、方法、属性等。与许多动态语言(如Python、JavaScript)不同,C++是一种静态类型的编译语言,缺乏内置的反射机制。RTTI(Run-Time Type Information)是C++的一部分,用于在运行时识别类型。C++虽然没有内置的反射机制,但通过使用RTTI、宏和模板以及第三方库(如RTTR),我们可以实现类似的反射功能。通过使用宏和模板,可以创建一个简单的反射系统。使用RTTR库的示例。

2024-07-10 19:28:34 1046

原创 C++中 Debug和Release的区别

在C/C++编程领域,Debug和Release是两种截然不同的编译模式,它们分别服务于不同的开发阶段和目标。Debug模式,通常称为调试版本,是专为开发人员设计的编译模式。在Debug模式下,编译器会尽可能保留源代码的结构和变量信息,以便在调试过程中能够清晰地反映程序的运行状态。在Debug模式下编译并运行此程序,如果a的值被意外修改为0,程序将在断言处中断,并显示错误消息。2.定期测试Release模式:随着开发的进行,应定期在Release模式下测试程序,以确保优化过程没有引入新的问题。

2024-07-09 16:51:35 506

原创 C++ 假设今天是星期日,那么过a^b天之后是星期几?

但是注意看a和b的取值范围,a^b的值会是一个非常大的值,远超出数值的表达范围了,所以我们要用到模运算的一些性质。模运算是基于整除的概念,给定两个整数a和m(m不为0),a除以m的余数记作a mod m,满足关系式a = k*m + r,其中k是整数(称为商),r是满足0 <= r < m的余数。其中,Monday是星期一,Tuesday是星期二,Wednesday是星期三,Thursday是星期四,Friday是星期五,Saturday是星期六,Sunday是星期日。

2024-07-08 17:30:05 1318

原创 C++ this 指针到底是个什么特殊的指针

/ 使用 this 指针区分成员变量和参数 } int getValue() { return this->value;2 常量成员函数:在常量成员函数中,this 指针的类型是 const,因此不能修改对象的成员变量。

2024-07-06 16:05:24 586

原创 C++ 彻底搞懂指针(终章)

int (*f[ ])(int),从 f 开始理解,先运算(*f[ ]),在(*f[ ])中,[ ]的优先级更高,f[ ]表明 f 是一个数组,*f[ ] 表明这是一个指针数组,然后剩下的 int(int)是指针数组中每个指针所指向的类型,是一个原型为 int func(int) 的函数,所以 f 是一个函数指针数组,int* (*f[ ])(int)类似,只不过函数原型为 int* func(int)。比如要创建一个存储10个int类型数据的数组,可以使用malloc函数,此时需要进行强制类型转换。

2024-07-05 08:04:34 625

原创 C++ 彻底搞懂指针(4)

我们说函数运行结束后会销毁所有的局部变量,这里所谓的销毁并不是将局部数据所占用的内存全部抹掉,而是说,后面的代码可以随意使用这块内存,上面的例子中,func运行结束后 n 的值还保持原样,是因为这块内存还没有被覆盖掉,那个位置的值只是暂时还没有变化,所以是有风险的。需要注意的是,结构体变量名和数组名不一样,数组名在表达式中会被转换为一个指针常量,结构体变量名不会,在任何地方结构体变量名都表示整个集合本身,要想取得结构体的地址,必须在前面加 & 才行。

2024-07-05 08:01:56 641

原创 C++ 彻底搞懂指针(3)

• 站在编译器的角度,变量名、数组名都是一个符号,需要和数据绑定起来,变量名表示一个数据,数组名表示一组数据,它们都是有类型的,上面数组 arr 的类型就是 int[5],表示一个拥有5个 int 数据的集合,那么长度就是4*5 = 20个字节,而 p 的类型是 int*,在32位环境中长度为4,在64位环境中长度为8。int **p是指向数组 arr 的指针,它的定义形式应该为 int *(*p),括号里面的 * 表示 p 是一个指针,括号外面的 int* 表示 p 指向的数据类型。

2024-07-03 18:26:36 1477

原创 C++ 彻底搞懂指针(2)

在上面这个例子中,指针 p 的类型是 int*,当执行 p++时,编译器的处理方法是将指针 p 加上 sizeof(int),在32位系统中,指针p就被加上了4,那这样的话,p就指向了 a[1],以此类推,p再加1,就指向了a[2]......*p++:* 和 ++ 的优先级相同,并且结合性都是从右向左,这意味着,在这个表达式中,首先考虑++运算符,后置++会先返回当前p,即a[0]的地址,然后p自增1,然后考虑 * 运算符,应用于p++的返回值,所以最终得到a[0],p指向a[1]

2024-07-03 18:25:38 709

原创 C++ 彻底搞懂指针(1)

但是,a究竟指向哪里呢,声明了变量a,但未对它进行初始化,所示我们没办法预测12这个值将被存储在什么地方,由此可以看出,指针变量和其他变量是一样的,如果变量是静态的,会初始化为NULL,如果变量是自动的,就不会初始化,无论是静态还是自动变量,声明一个指向整型的指针都不会创建用于存储整型值的内存空间。在上面这段代码中,a 和 *p1的结果是一样的,p1本身的值是一个地址,*p1表示获取该地址上的值,也就是变量a的值,这个过程也被称为解引用。当有人问起,什么是指针时,我会毫不犹豫地回答,指针变量存放的是地址!

2024-07-02 12:08:34 621

原创 C/C++ 中的强大组合:指针与函数

注意:函数不要返回普通局部变量的地址,返回普通局部变量的地址会出现段错误,使用一个已经释放的内存空间的行为是未定义的。但是,可以返回静态变量的地址,因为静态变量的生命周期是整个进程,所以是一个合法的地址。C++中指针和函数有着紧密的联系,指针可以用来存储函数的地址,通过指针调用函数或者将函数作为参数传递给其他函数。

2024-07-01 17:36:35 819

原创 C/C++ 语言初学者必备:字符串处理函数入门

其中,参数dest是目标字符串(也就是要拷贝到的字符串),src是源字符串(也就是要被拷贝的字符串),n是要拷贝的最大字节数(如果遇到'\0'会自动结束)。其中,参数str是一个指向要写入数据的字符数组的指针,参数format是一个包含格式化占位符(如%d、%f等)的字符串,后面可跟多个与占位符相对应的实际值。其中,参数str是一个指向要读取数据的字符数组的指针,参数format是一个包含格式化占位符(如%d、%f等)的字符串,后面可跟多个与占位符相对应的实际值。如果没有'\0'结尾,则结果未定义。

2024-07-01 17:35:12 358

原创 python工程打包成exe

示例:`nuitka --include-plugin-directory=/path/to/plugin myscript.py`- 示例:`nuitka --recurse-not-to=module1,module2 myscript.py`- 示例:`nuitka --macos-icon=/path/to/icon.icns myscript.py`- 示例:`nuitka --linux-icon=/path/to/icon.png myscript.py`

2024-06-30 22:36:09 1051

原创 C++ 函数进阶:内联函数、重载、默认参数、占位参数

比如上面举的例子,C++中调用C语言实现的myFunc函数,在链接阶段会去找_Z6myFuncv,结果是找不到,因为void myFunc(){}函数是C语言编写的,生成的函数名是myFunc。本文主要探讨了C++中的关键概念:内联函数、函数重载以及函数的默认参数,这些特性极大地丰富了编程语言的功能,提高了代码的复用性和执行效率。C++函数重载是指在一个类中定义多个同名函数,这些函数的参数列表不同(参数数量、类型或顺序等),以便根据调用时传递的实参来选择合适的函数进行调用。3 函数的默认参数。

2024-06-29 14:13:00 1255

原创 C++为什么将 0.1f 更改为 0 性能会降低 10 倍

在C++编程中,将0.1f更改为0可能导致性能大幅下降的原因是多方面的,包括数据类型表示的差异、CPU指令集的不匹配以及编译器优化的变化。为了避免这种性能下降,程序员应该谨慎处理数据类型的更改,并进行充分的性能测试和优化。然而,在某些情况下,如果编译器无法进行有效的优化,这个循环就会变成一个空转循环(busy-wait loop),浪费了大量的CPU周期。此外,即使编译器能够优化掉这个无效的循环,但在源代码层面的这种更改仍然可能导致编译器重新评估和优化整个函数或代码块,这可能会引入额外的开销。

2024-06-29 14:11:38 528

原创 C++ RTTI: 让你的代码更灵活

总的来说,RTTI为C++开发者提供了一种在运行时操作类型信息的强大机制,极大地增强了代码的灵活性和可扩展性。总之,RTTI是C++中一个非常有用的特性,它为我们的代码带来了更强的灵活性和可扩展性。RTTI需要编译器在编译时生成额外的类型信息,并在运行时进行类型检查,这会带来一定的性能开销。因此在使用RTTI时需要格外小心,确保类型转换是安全的。在某些情况下,RTTI仍然是一个很好的选择,但我们需要审慎地使用它,权衡各种因素。利用模板,我们可以编写泛型代码,在编译时进行类型检查,无需在运行时使用RTTI。

2024-06-28 17:12:38 552

原创 C++ STL: std::vector与std::array的深入对比

然而,动态内存分配和重新分配的开销使得std::vector在某些操作(如频繁的插入和删除)上性能不如std::array。由于其内存是在栈上分配的,不涉及动态内存分配和复制,std::array在某些场景下比std::vector更高效。性能方面,std::array由于其静态内存分配和固定大小,访问速度比std::vector更快。// 访问元素 std::cout << "Element at index 2: " << arr.at(2) << std::endl;

2024-06-28 17:10:56 530

原创 C++高频面试题——内存管理、堆栈、指针

另外,在实际开发中,推荐优先使用 C++ 的 new/delete 操作符以及容器类(如 std::vector、std::unique_ptr 等),避免手动管理动态内存带来的错误和麻烦。如果程序没有正确管理分配的内存,并且向已分配的堆块写入超过其边界范围之外的数据,就会导致堆溢出。• 使用智能指针:C++ 提供了智能指针类(如 std::unique_ptr、std::shared_ptr),它们能自动管理对象的生命周期和相关资源的释放,在对象不再使用时自动调用析构函数并释放相应的内存。

2024-06-27 18:29:45 661

原创 四招轻松从C++序列容器中移除元素,你学会了吗?

即,要删除的元素位于std::remove返回的迭代器定义的范围和集合的末尾。4 从序列容器中删除重复项:利用std::unique算法可以删除相邻的重复项,但需要注意该算法只删除相邻的重复项,并且不能改变容器的大小,需要配合erase方法来实现删除整个容器中的重复项。对于deque来说,会有一点点不同:参考cppreference.com,所有迭代器和引用都无效,除非被删除的元素位于容器的末尾或开头,在这种情况下,只有迭代器和对被删除元素的引用无效。注意,在范围末尾剩下的元素的值是未指定的。

2024-06-27 13:23:39 850

原创 C++ 中,extern c 是什么意思?

extern "C"是C++中的一个重要特性,它允许C++代码与C语言代码进行互操作。通过使用extern "C"声明,我们可以确保C++编译器以C语言的链接方式对特定的函数或变量进行处理,从而实现两种语言之间的无缝集成。在实际开发中,这一特性对于创建跨语言的库和应用程序至关重要。

2024-06-26 19:42:22 631

原创 讨论万能头文件<bits/stdc++.h> 在C++中的使用

尽管 <bits/stdc++.h> 在某些情况下(如编程竞赛)可能是一个方便的工具,但在实际的软件开发中,明确并精确地包含你需要的头文件通常是更好的做法。在上面的示例中,通过明确包含 <vector>, <algorithm>, 和 <iostream>,我们避免了使用非标准的 <bits/stdc++.h>,同时提高了代码的清晰度和可移植性。2 可移植性:<bits/stdc++.h> 不是C++标准的一部分,因此在非GCC编译器上可能无法使用,降低了代码的可移植性。// 使用输出流打印结果。

2024-06-26 19:41:03 632

原创 Python制作短信发送程序

并获取模板ID备用。

2024-06-25 22:51:39 732

原创 详解Python 66 个内置函数

46.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): 打开一个文件,并返回文件对象。11.compile(source, filename, mode[, flags[, dont_inherit]]): 编译源代码为代码或AST对象。print(list(zipped)) # 输出:[(1, 'a'), (2, 'b'), (3, 'c')]

2024-06-25 14:55:40 1125

原创 C++之Qt执行耗时操作导致界面卡顿的解决办法

使用更高效的排序算法:排序是计算中常见的任务,不同排序算法的时间复杂度可能从O(n)到O(n^2)不等。将耗时操作分解为多个较小的任务,并使用多线程或异步操作逐个执行这些任务,是一种非常有效的策略,用于提高应用程序的响应性和用户体验。在C++中使用Qt框架时,执行耗时操作可能会导致界面卡顿,因为耗时操作会阻塞主线程(通常是GUI线程),从而无法及时响应用户输入或更新界面。当面对复杂的计算任务或大量的数据处理时,选择适合的算法和数据结构能够显著减少计算时间,从而提高程序的响应速度和整体性能。

2024-06-24 17:37:40 667

原创 c++过度使用智能指针

int main() { // 不恰当的使用:使用std::unique_ptr管理固定数量的学生对象 std::vector<std::unique_ptr<Student>> students;在设计时,需要明确每个资源的生命周期和管理责任,避免在不需要自动管理内存的情况下使用智能指针,从而保持代码的简洁性和高效性。过度使用智能指针的意思:在不需要自动管理资源的情况下滥用智能指针,比如对于栈上分配的对象或静态分配的资源使用智能指针。案例2:静态分配或者单例模式的过度包装。

2024-06-24 16:27:36 329

原创 C++为何引入array而非直接使用vector?

3 简化的接口:与原生数组相比,std::array提供了更安全的迭代器支持和丰富的成员函数,如at()、size()、empty()等,这使得操作固定大小的数组变得更加方便和安全。• std::vector则需要根据元素的添加动态分配内存,这可能会涉及到内存的重新分配和现有元素的拷贝,因此在性能上可能略逊于std::array。std::array是一个固定大小的容器,其大小在编译时确定,而std::vector则是一个动态数组,可以在运行时改变大小。这是两者最本质的区别。

2024-06-24 11:52:07 334

原创 使用 CMake 和 C++ 创建可重用库详细方法和步骤

您将学习:使用 CMake 创建可重用库的动机和好处项目结构和主要组成部分概述如何在项目中使用外部库和依赖项如何构建和安装库并在其他应用程序中使用它在本指南结束时,您将对如何使用 CMake 创建可重用的库以及如何将这些原则应用于您自己的项目有深入的了解。这种方法的好处是多方面的:它减少了代码重复和复杂性,确保了代码的质量和一致性,提高了不同项目的可移植性和兼容性,增强了性能和可伸缩性,并促进了测试和调试。使用 CMake 创建可重用的 C++ 库的旅程揭示了软件开发的强大范式,促进了效率、模块化和协作。

2024-06-23 22:21:00 692

原创 掌握CMake基础:从零开始实战编译工程

1 使用cmake 构建Hello World 程序的全部过程,并介绍三个简单的指令:PROJECT/MESSAGE/ADD_EXECUTABLE 以及变量调用的方法,同时提及了两个隐式变量 < projectname >_SOURCE_DIR 及< projectname >_BINARY_DIR,演示了变量调用的方法,从这个过程来看,可能觉得比直接写 Makefile 要复杂多了,甚至都可以不编写Makefile,直接使用gcc -o hello -c main.c 即可生成需要的目标文件。

2024-06-23 13:10:14 928

原创 C#实现自定义样式的标签打印

在设置模板前需要用的标签设计工具,在这里我推荐使用bartender,它可以绑定数据源、设计模板样式,完全能满足标签打印的需求,如果有好的方式也请大家在评论区讨论。批量打印软件需要根据具体的业务逻辑实现,比如通过接口获取后台的待打印列表,这些因项目而异,这里也没办法一次实现,现在主要说明一下bartender模板调用的问题。在工业上位机开发环境中,经常会用到自定义批量打印标签的情况,比如合格证、生产单等,这是实现自动化的一个重要步骤,在这里我介绍一下我的具体实现方式。

2024-06-22 23:34:59 986 1

原创 C++ STL容器操作:6种常用场景算法

日常开发中的容器操作,如查找、删除、排序、分割、拷贝和合并,均可借助STL中的精选算法高效完成。• 作用:重新排列容器元素,使得所有不满足谓词条件的元素被放置在容器的前端。配合earse实现移除不匹配元素。• 作用:重新排列容器元素,使得所有不匹配特定值的元素被放置在容器的前端。• 作用:用于在指定范围内将所有匹配某个值的元素替换为另一个值,拷贝到另一个的容器中。• 作用:分割容器,使满足谓词的元素在前,不满足的在后。• 作用:满足谓词条件的元素,替换为指定的替换值。

2024-06-22 21:21:18 473

原创 C++ std::thread 线程创建和启动

使用函数指针或成员函数指针:如果线程函数是一个全局函数、静态成员函数或非静态成员函数,可以直接将函数指针或成员函数指针作为参数传递给 std::thread 构造函数。使用 std::mutex、std::condition_variable 或 std::atomic 等同步机制,可以自定义线程状态的检查和控制。std::thread 是C++11标准引入的一个轻量级线程库,它提供了创建和管理线程的能力,方便用户创建新的线程,并执行指定的函数。定义线程函数:首先需要定义一个函数,作为线程的入口点。

2024-06-21 18:36:06 1167

原创 C++ 线程 多线程 线程池

b.对线程进行管理要求额外的CPU开销,线程的使用会给系统带来上下文切换的额外负担;当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。线程:线程是操作系统调度的最小单元,每个线程都拥有各自的计数器、堆栈和局部变量等属性,在进行中负责程序执行的执行单元,多个线程组成了一个进程,一个进程中至少有一个线程。它可以在应用程序中预先创建一组线程,然后将任务分配给这些线程,以便在不同的任务之间共享线程资源,并避免不断创建和销毁线程的开销。

2024-06-21 18:33:00 382

原创 C++ TheadPool 线程池实现

此情况发生情形3且设置了任务缓冲队列大小后面,主程序添加第N个任务,添加后发现池子中的线程用完了,任务缓冲队列也满了,于是进入等待状态、等待任务缓冲队列中的任务腾空通知。此情况基于情形1,所有工作线程已处在等待状态,主线程开始添加三个任务,添加后通知(notif())唤醒线程池中的线程开始取(take())任务执行. 此时的任务缓冲队列还是空。此情况发生情形2后面,所有工作线程都在工作中,主线程开始添加第四个任务,添加后发现现在线程池中的线程用完了,于是存入任务缓冲队列。

2024-06-21 18:28:42 863

原创 OpenCV二维码检测流程全解析

引入必要的OpenCV和C++库首先,程序包含了OpenCV库和C++标准库的头文件,这些库提供了处理图像所需的各种功能。#include <opencv2/core.hpp> // OpenCV核心功能#include <opencv2/imgcodecs.hpp> // 图像编解码#include <opencv2/highgui.hpp> // GUI#include <opencv2/imgproc.hpp> // 图像处理#include <iostream> // 输入输出流#include <

2024-06-21 16:30:44 677

原创 STM32串口设计与上位机对接技术

/读取接收到的数据 USART2_RX_BUF[uart2_i++]=r;//串口初始化 while(1) { if(usercmd_en==1) // 需要重新定义 USART2_RX_STA { // usercmd 需要重新定义 USART2_RX_BUF if(strcmp(usercmd,"AT")==0) printf("ok\r\n");

2024-06-21 12:12:26 887

原创 全面解析机器视觉工业缺陷检测(光源,相机,镜头,算法)

一般机器视觉系统:相机、镜头、光源、运动系统。 视觉工业检测大体分为工件尺寸测量与定位,和表面缺陷检测,及各种Logo标识的检测与识别等。尺寸测量主要是检测物体的长、宽、高,比较常见主要是物体的二维尺寸(宽和高)检测。表面缺陷检测主要是物体表面局部物理或者化学性质不均匀的区域,比较常见的有金属或者塑料制品表面的划痕(如:手机壳/屏幕表面的划痕)、斑点和孔洞(如:PCB板漏了焊点或者表面多了焊点),纸张表面的色差、脏污点、破损,纸制品表面的压痕、凸起,玻璃等非金属

2024-06-20 12:07:56 1580

原创 相机SDK开发C++篇-常用开发函数封装讲解(迈德威视相机)

/ 软触发失败,返回false } return true;= (nRet = CameraSetSysOption("NumBuffers", QString("%1").arg(getImageBufferNodeNum()).toLocal8Bit().data()))) { setLastErrorMsg("相机#%1设置缓存区数量错误,错误码:%2").arg(getCameraIndex()).arg(nRet);

2024-06-20 11:15:05 483

原创 相机SDK开发C++篇—常用开发函数封装讲解(大华相机)

(ret=IMV_SetBufferCount(devHandle,getImageBufferNodeNum()))) { setLastErrorMsg("C17-1: 相机#%1设置图像缓存节点数量失败,错误码:%2").arg(getCameraIndex()).arg(ret));= ret) { setLastErrorMsg("C12: 相机#%1注册回调函数失败:%2").arg(getCameraIndex()).arg(ret));

2024-06-20 11:10:35 535

原创 C++ 中把 int 转换成 string 的最简单方法

std::cout << "转换后的字符串是: " << str_number << std::endl;std::cout << "转换后的字符串是: " << str_number << std::endl;std::cout << "转换后的字符串是: " << str_number << std::endl;•通过将buffer作为构造函数的参数来创建一个std::string对象str_number。

2024-06-20 10:45:19 955

原创 3D视觉机械手眼标定仿真

本仿真假设,已经可以获得特征在相机坐标系下的位姿,基于这些位姿,进行标定(即完成AX =XB的求解)。

2024-06-20 08:24:56 1121

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除