- 博客(15)
- 收藏
- 关注
原创 设计模式详解
点击按钮(发起者)后,并不直接执行操作,而是生成一个命令对象(如“复制命令”),由命令对象去调用具体的执行者(如文档)。• 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。• 使用场景:在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。• 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。游戏中渲染大量相同的树,树的纹理和模型是内部状态(可共享),树的位置是外部状态(不可共享)。
2025-10-09 15:23:59
453
原创 理解内存顺序
重排序是指编译器或处理器为了优化性能,可能会改变指令的实际执行顺序,但这种改变在单线程环境下不会影响程序的最终结果。memory_order_release会插入适当的内存屏障,确保所有之前的写操作对其他线程可见后,才执行release操作。在讨论内存顺序时,"后续操作被重排序到该操作之前"是一个关键概念。• 线程1中所有在ready.store之前的操作(操作A)不会被重排序到它之后。• 线程2中所有在ready.load之后的操作(操作D)不会被重排序到它之前。理解"后续操作被重排序到该操作之前"
2025-09-25 16:57:27
250
原创 为什么static_cast由基类向派生类转换是不安全的
static_cast 的基类到派生类转换是“不安全”的,因为它依赖程序员手动保证类型正确性,编译器无法提供保护。对象类型不匹配:static_cast 在编译时执行类型检查,但无法在运行时验证对象的实际类型。潜在的内存布局问题:派生类可能包含额外的成员变量或虚函数,若强制转换一个实际为基类的对象,访问这些派生类独有的部分会越界访问内存。• 使用 dynamic_cast:对多态类型(含虚函数)进行运行时检查,失败时返回 nullptr(指针)或抛出异常(引用)。
2025-09-19 10:56:54
341
原创 虚函数的调用关系
它允许子类重写(override)父类的函数,并在运行时根据对象的实际类型动态决定调用哪个版本的函数。• 运行时多态:通过基类指针或引用调用虚函数时,实际调用的是对象所属类的版本,而不是指针/引用的静态类型。// 调用 Derived::show(),而不是 Base::show()// 如果 Base 的析构函数不是虚的,只会调用 Base::~Base()• 由于 show() 是虚函数,编译器会在运行时查找 Derived 的 show() 版本。// 调用 Derived::show()
2025-09-18 19:57:28
848
原创 Name Return Value Opmization
Named Return Value Optimization (NRVO) 是一种编译器技术,它允许编译器直接在函数外部接收对象的内存位置上构造那个即将被返回的命名局部对象。从而避免了拷贝构造和移动构造的发生。配合使用移动语义:即使在最坏的情况下 NRVO 没有发生,C++11 后的语言规则也会优先尝试使用移动构造而非拷贝构造(只要你的对象提供了 noexcept 的移动构造函数),这仍然比深拷贝要好得多。// 直接在使用者提供的内存上(即 _hidden_address 指向的位置)构造对象 w。
2025-09-18 16:43:38
514
原创 静态建立和动态建立
在编程中,静态分配(Static Allocation)和动态分配(Dynamic Allocation)是两种不同的内存管理方式,核心区别在于内存分配时机、生命周期和管理方式。• 内存位置:通常存储在数据段(全局/静态区)或栈(局部静态变量)。• 缺点:管理复杂(需手动释放)、有运行时开销(分配/释放操作)。• 分配时机:编译时或程序启动时(如全局变量、静态变量)。• 优点:高效(无运行时开销)、安全(不会内存泄漏)。• 生命周期:从分配开始到显式释放为止(需手动管理)。
2025-05-21 16:11:26
386
原创 定义和声明的区别
在编程中,定义(Definition)和声明(Declaration)是两个相关但不同的概念,主要区别在于是否分配内存或实现细节。• 作用:告诉编译器某个标识符(变量、函数、类等)的存在及其类型,但不分配内存或提供具体实现。• 避免重复定义:通过声明允许多文件共享同一标识符,而定义仅在一处实现。• 作用:为标识符分配内存或提供具体实现(如函数体、类成员等)。• 声明通常出现在头文件(如C/C++)或需要提前引用的地方。• 定义同时也是声明(即定义包含声明的作用)。)中放定义(如函数实现、全局变量)。
2025-05-21 16:07:34
619
原创 push_back()和emplace_back()
等)用于在尾部添加元素的成员函数,但它们在实现方式和效率上有重要区别。在 C++11 及以后的代码中,对于已知构造参数的情况,两者性能几乎无差别,编译器会优化掉额外开销。这两个方法都是 C++ 标准库容器(如。• 当参数需要隐式转换时(更清晰)• 代码需要兼容 C++98。对于简单类型(如 int)• 已有构造好的对象要添加。• 当构造参数已知时。
2025-05-07 17:55:28
315
原创 std::move
是 C++11 引入的一个关键工具,用于实现高效的资源转移(移动语义)。它实际上并不移动任何数据,而是将对象转换为右值引用,从而允许移动操作的发生。是现代C++高效资源管理的基础工具,正确理解和使用它可以显著提升程序性能,特别是在处理大型对象或资源密集型操作时。许多情况下(如返回值优化),编译器会自动优化,不需要显式使用。• 启用移动:允许调用移动构造函数和移动赋值运算符。本身不执行任何移动操作,只是转换值的类别。• 转换语义:将左值转换为右值引用。不要移动局部变量后继续使用。const对象无法移动。
2025-05-07 17:23:25
335
原创 内存泄漏的检测
Valgrind 是一个强大的内存调试和性能分析工具集,而 C 运行时库 (CRT) 是 C/C++ 程序运行的基础库。不同平台的 CRT 实现(如 glibc、MSVCRT、ucrt)在 Valgrind 下的表现可能略有不同,但核心检测功能都能正常工作。Valgrind 是检测 CRT 相关内存问题的强大工具,正确使用可以显著提高代码质量和稳定性。Valgrind 与 C 运行时库 (CRT) 的关系及使用。现象:Valgrind 报告 CRT 内部的内存使用为问题。Valgrind 的基本功能。
2025-05-07 16:17:49
267
原创 std::string::npos
是 C++ 字符串操作中非常重要的一个概念,正确理解和使用它可以编写出更健壮的字符串处理代码。类的一个特殊静态常量,表示"不存在的位置"或"无效位置"。• 含义:表示字符串中不存在的索引位置。转换为无符号类型会变成最大值)当字符串查找操作失败时,返回。是 C++ 标准库中。
2025-05-07 15:40:16
977
原创 malloc和free的原理
是 C 标准库中的内存管理函数,它们管理着程序的堆内存。内存对齐:通常按 8 或 16 字节对齐分配的内存。• 如果找到的空闲块比请求的大,将其分割为两部分。线程局部存储:多线程环境下使用线程特定的内存池。地址计算:根据返回的指针计算出内存块头部地址。• 首先在空闲内存链表中查找足够大的空闲块。小块分配:对小内存请求使用特殊的高效分配器。• 外部碎片:空闲内存分散,无法满足大请求。• 如果是,合并它们成为一个更大的空闲块。• 如果空闲链表没有足够大的块,调用。• 内部碎片:分配的内存比请求的大。
2025-05-07 15:20:28
687
原创 bochs安装
bochs安装/configure->make之后报错缺少库文件,安装需要的库文件之后重新make,报错。解决方法:/configure之后重新安装了库的话,要重新/configure,然后再make。make: *** [Makefile:183:bochs] 错误 1。
2025-03-04 16:13:25
530
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅