
#C++基础
文章平均质量分 90
以C++的基础知识为主,如语法等等
流星雨爱编程
记录工作的日常,心得体会
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
面试题:C++虚函数可以是内联函数吗?
C++中的虚函数和内联函数看似矛盾,但在特定情况下可以共存。虚函数通过inline关键字声明为内联函数时,是否内联取决于调用方式。当编译器能确定具体调用对象(如通过对象直接调用),虚函数可以被内联;而在多态调用(通过指针或引用)时,由于需要在运行时通过虚函数表确定具体函数,无法内联。最终,内联的决定权在编译器,它可能根据优化级别和调用情况忽略inline请求或内联未标记的函数。因此,虚函数的内联性取决于调用上下文和编译器的优化策略。原创 2025-05-12 22:55:28 · 266 阅读 · 4 评论 -
for(auto it: vec)和for(auto& it: vec)的区别以及使用场景
for(auto it: vec)适用于只需要读取容器元素值的场景,会复制元素的值,可能存在性能开销。for(auto& it: vec) 适用于需要修改容器元素值的场景,通过引用直接操作容器元素,避免了复制开销。此外,若你不希望修改元素,同时又想避免复制大对象带来的开销,可以使用或或这样it是元素的常量引用,既能避免复制,又能防止意外修改元素。原创 2025-04-28 23:06:50 · 536 阅读 · 6 评论 -
C++中使用相对目录的优缺点
最近在一个C++的项目中使用了相对目录,代码如下:在我自己的电脑上程序运行起来,在当前工作目录下可以生成logs目录,而且在logs目录下生成了日志文件ServiceTerminal.txt,但是在同事的电脑上,同样的代码,调试运行却不能生成ServiceTerminal.txt文件,然后在这行代码之前增加打印当前的工作目录代码:经过调试发现currentPath指向的工作目录不对,然后打开工程配置(vs2019工程)发现:调试环境的工作目录配置不对,修改后再次调试,可以生成ServiceTermin原创 2025-03-08 13:59:22 · 819 阅读 · 1 评论 -
C++标准库之std::begin、std::end、std::pre和std::next
可以为不暴露适合的begin()和end()成员函数的类提供begin和end的自定义重载,从而能迭代它。(C++11)(C++11)特化std::begin和std::end(函数模板)(C++11)(C++11)特化的std::begin和std::end(函数模板)基于范围的 for 循环支持(函数)基于范围的 for 循环支持(函数)同swap的使用(描述于可交换 (Swappable)),begin函数在泛型语境中的使用等价于 using std::begin;原创 2024-10-27 15:57:28 · 1854 阅读 · 2 评论 -
宏定义中的#、##、__VA_ARGS__和...的含义和作用
从上面的例子我们可以看到,宏展开时仅仅是执行了文本替换,所以当传递给类函数宏的参数是一个表达式时或者类函数宏是一个表达式的一部分时,就要特别宏展开的形式是否符合预期,按需对宏参数加上小括号是一种很好的处理方法(甚至需要对宏替换内容的每个参数加一个小括号),比如下面这样。这样就不怕x或y是表达式了,因为小括号的优先级非常高。宏按照使用形式还可以分为#define定义的普通宏和#ifdef、#ifndef等定义的条件宏,这些都是比较基础的知识。原创 2024-10-23 23:11:43 · 2347 阅读 · 13 评论 -
java实现类似C++的union
在C++中有一种用户自定义数据类型叫联合体union,它允许你在相同的内存位置存储不同的数据类型。与结构体(struct)不同,结构体中的所有成员都占用各自的内存空间,而union的所有成员共享同一块内存区域。因此,union的大小等于其最大成员的大小。。原创 2024-10-23 21:03:08 · 477 阅读 · 0 评论 -
申请空间时malloc(0)会发生什么?
那么根据C标准(C99及之后的版本),结果是未定义的(undefined behavior)。然而,在实际实践中,大多数平台和编译器对。意思就是当malloc接收到一个大小为0的请求时,其行为是由实现定义的。也就是说不同的实现可以选择不同的处理方式。许多实现选择在这种情况下返回NULL,因为分配0字节的内存没有实际用途。函数申请内存空间时,传递的参数指定了你希望分配的字节数。如果你传递的参数是0,即。实际动手可以发现,mallc(0)返回的指针不是空指针。的行为有一个共同的处理方式。原创 2024-10-13 18:22:10 · 413 阅读 · 0 评论 -
C++生成唯一值的五种方法
生成唯一值是软件开发中的一项重要任务,C++提供了多种实现方法。使用标准库中的随机数生成器可以生成随机唯一值,但在高并发环境下可能重复。利用时间戳和计数器组合生成唯一值简单有效,但在多线程环境下需要同步机制。通过UUID生成唯一值具有高度唯一性,适用于分布式系统等场景。在实际应用中,应根据具体需求和环境选择合适的方法。原创 2024-09-14 17:24:29 · 2432 阅读 · 19 评论 -
深入理解 C++ 中的 static_assert 编译期断言
是 C++11 提供的一个非常实用的工具,能够在编译期对程序中的一些关键条件进行检查,避免运行时错误。通过其灵活的断言机制,不仅能提高代码的可维护性,还能在模板编程、类型检查等场景中发挥重要作用。借助编译期的强约束,开发者可以编写出更加健壮的程序。原创 2024-09-10 21:39:29 · 1425 阅读 · 1 评论 -
C++ 中的 override 和 overload的区别
在重写基类虚函数时,始终使用override关键字,确保编译器检查函数签名的正确性,避免意外的错误。在进行函数重载时,确保参数列表的差异足以让编译器进行区分,同时保证函数的语义一致性。如果需要在子类中使用基类的重载函数,使用using关键字显式引入基类的函数,避免隐藏问题。总之,在 C++ 中,理解override和overload的区别是掌握面向对象编程的重要一步。override强调的是子类对基类虚函数的重写,是实现多态的基础。而overload则允许同一作用域内定义多个功能类似但参数不同的函数。原创 2024-09-07 23:40:51 · 1779 阅读 · 1 评论 -
C++中的mutable关键字详解
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。我们知道,被const关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以使用类中的所有成员变量,但是不能修改他们的值。然而,在某些特殊情况下,我们还是需要在const函数中修改类的某些成员变量,因为要修改的成员变量与类本身并无多少关系,即使修改了也不会对类造成多少影响。当然,你可以说,你可以去掉该函数的const关键字呀!原创 2024-09-07 11:03:37 · 973 阅读 · 0 评论 -
为什么变量不可以在 switch 语句中声明定义?
变量不能在switch语句中声明定义的主要原因是作用域和跳转语句的限制。为了避免潜在的作用域冲突和未定义行为,我们应该在switch语句之前声明所有必要的变量,或者使用花括号在case分支中创建新的作用域(在支持C99或更高标准的编译器中)。通过遵循这些最佳实践,我们可以确保代码的清晰性和稳定性。原创 2024-06-26 08:18:34 · 1769 阅读 · 15 评论 -
C++ 如何高效的使用 STL 容器?
在使用C++标准模板库(STL)中的容器时,对象复制的常见情况和复制的实现方式是重要的考虑因素。对象的复制通常通过复制构造函数和复制赋值运算符来完成,这两个函数是类的成员函数,用于创建类的新对象或将一个对象的值赋给另一个对象。然而,对象的复制可能会导致性能问题,特别是当对象的复制成本很高时。此外,如果有一个对象,其中“复制”有一个非常规的含义,那么将这样的对象放入容器可能会导致问题。在存在继承的情况下,复制可能会导致切片问题。原创 2024-04-27 23:23:59 · 1291 阅读 · 8 评论 -
#ifndef vs #pragma once, 哪个更好用?
在C++编程中,头文件守卫(Header Guard)是一种防止头文件内容在同一编译单元中被多次包含的技术。这种重复包含可能导致编译错误,如类型重定义或变量多重声明。为了解决这个问题,开发者通常使用预处理指令来确保头文件只被包含一次。最常见的两种方法是使用#ifndef#define#endif宏(也称为传统的头文件守卫)和指令。原创 2024-04-18 21:42:49 · 1109 阅读 · 1 评论 -
C++之std::initializer_list详解
类的构造函数可以接受 std::initializer_list 参数,以便在创建对象时使用初始化列表进行初始化。public:private:从上面可以看到,使用std::initializer_list的优点:1)灵活性和扩展性:std::initializer_list可以用在任何需要可变数量参数的函数中,提供了高度的灵活性和扩展性。例如,你可以写一个接受std::initializer_list 参数的函数,让它可以接受任意数量的元素进行初始化。2)原创 2024-04-09 22:39:46 · 3154 阅读 · 1 评论 -
原生数组和std::array异同
std::array的优点:固定大小:std::array的大小在编译时确定,这有助于避免运行时的大小检查和可能的性能开销。更好的类型安全:与原生数组相比,std::array提供了更好的类型安全,因为它是一个类模板,而不是简单的数组类型。支持STL算法:由于std::array提供了迭代器接口,因此可以很方便地与STL算法一起使用。成员函数和接口:std::array提供了一系列有用的成员函数,如size(), empty(), begin(), end()等,这些功能在原生数组上是没有的。原创 2024-04-08 23:14:46 · 1336 阅读 · 9 评论 -
C/C++中decltype关键字用法总结以及与typeinfo区别
decltype可以作用于变量、表达式及函数名。①作用于变量直接得到变量的类型;②作用于表达式,结果是左值的表达式得到类型的引用,结果是右值的表达式得到类型;③作用于函数名会得到函数类型,不会自动转换成指针。总的来说,decltype在C++中是一个非常强大的工具,它允许开发者以更简洁和灵活的方式处理复杂的类型问题。原创 2024-04-06 10:24:20 · 3852 阅读 · 5 评论 -
C/C++中const关键字用法总结
使用const还有很多好处:1) 类型安全:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。2) 可以节省空间,避免不必要的内存分配: const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象宏一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而宏定义的常量在内存中有若干个拷贝。原创 2024-04-05 18:58:59 · 1193 阅读 · 1 评论 -
C/C++中static关键字用法总结
在使用关键字static的时候,我们需要注意一下几个原则:被static修饰的变量的存储位置都在静态区,且生命周期延长至整个程序运行结束。static具有隔离作用,被static修饰的全局变量和全局函数的作用域由全局变为当前文件。静态变量虽然具有全局变量的生命周期,但只能作用于自己的作用域。普通静态成员需要在类的外面进行初始化。静态成员函数不能调用类的非静态成员,包括非静态成员和非静态成员函数。原创 2024-04-04 22:37:55 · 1244 阅读 · 7 评论 -
预处理 #pragma 命令详解
总的来说,#pragma是一个强大的工具,但应该谨慎使用,确保它不会导致代码在不同编译器或平台上的不可移植性。原创 2024-03-19 21:57:02 · 2349 阅读 · 0 评论 -
C/C++中{}的用法总结(全)
{} 可以用于定义枚举类型,其中包含一组可能的值。Opt1,Opt2,Opt3//C++11之后版本可以加class,限制枚举的作用域,如:Opt1,Opt2,Opt3{} 可以用于定义Lambda函数。Lambda函数是一种匿名的函数对象,可以在函数中传递。在 C++ 中,我们建议尽可能使用列表初始化(即大括号 {})。这种初始化方式可以提供更一致的语法,防止窄化转换,避免 “最令人困惑的语法” 问题,还可以用于初始化任何类型的对象,包括基本类型、数组、结构体,以及类的成员变量。原创 2024-03-14 12:54:01 · 3728 阅读 · 30 评论 -
从汇编来角度剖析C语言函数调用过程
当一个c函数被调用时,一个栈帧(stack frame)是如何被建立,又如何被消除的。这些细节跟操作系统平台及编译器的实现有关,下面的描述是针对运行在Intel奔腾芯片上Linux的gcc编译器而言。c语言的标准并没有描述实现的方式,所以,不同的编译器,处理器,操作系统都可能有自己的建立栈帧的方式。原创 2024-03-13 22:54:35 · 1432 阅读 · 10 评论 -
C++17之折叠表达式
折叠表达式是一个强大的工具,但也需要谨慎使用。它可以使代码更简洁、更易于阅读,但也可能会使代码更难以理解。在使用折表达式之前,确保你理解了它的工作原理,并考虑是否有其他更直观的方法可以达到相同的效果。原创 2024-02-26 21:51:23 · 2125 阅读 · 8 评论 -
有了NULL,为什么C++还需要nullptr?
综上所述,尽管C++已经有了NULL来表示空指针,但引入nullptr提供了更高的类型安全性、避免了函数重载时的歧义,并增加了代码的清晰性和可读性。因此,在现代C++编程中,推荐使用nullptr来代替NULL表示空指针。原创 2024-02-17 08:53:54 · 1698 阅读 · 24 评论 -
C++ new 和 malloc 的区别?
new/delete提供了更符合 C++ 面向对象特性的内存管理方式。它们处理类型安全、对象生命周期(构造和析构)、异常安全以及简化语法。然而,这些改进也带来了一定的性能开销,这在某些性能敏感的应用中可能是一个考虑因素。在 C++ 中,new/delete是推荐的方式,因为它们提供了更安全和便利的内存管理机制。C++内存分配策略-优快云博客。原创 2024-02-15 10:53:07 · 1671 阅读 · 15 评论 -
浮点数详解
浮点数编码转换采用的是IEEE 规定的编码标准,float 和 double 这两种类型数据的转换原理相同,但由于表示的范围不一样,编码方式有些许区别。IEEE规定的浮点数编码会将一个浮点数转换为二进制数。以科学记数法划分,将浮点数拆分为3部分:符号、指数、尾数。原创 2024-01-23 07:28:14 · 1788 阅读 · 13 评论 -
深入理解STL空间分配器(四):bitmap_allocator
bitmap_allocator申请内存,是先从上一次分配block的超级块中,往后查找未使用的block分配,若超级块中block都已分配,则从_S_mem_blocks容器内往后查找下一个超级块。如果_S_mem_blocks容器内没有超级块了,则从内存池free_list中申请超级块,并将其缓存到S_mem_blocks容器内,以待后续分配使用。_S_mem_blocks容器内的超级块没有按大小升序排列,而内存池free_list中的超级块是按大小升序排列的。转载 2024-01-09 22:59:20 · 309 阅读 · 0 评论 -
深入理解STL空间分配器(三):pool_allocator
pool_allocator是一种基于单锁内存池的空间分配器,其内部采用内存池思想,通过构建16个空闲内存块队列,来进行内存的申请和回收处理。每个空闲队列管理的内存块大小固定,且均为8的倍数,范围从8到128字节,按8的倍数递增。该空间分配器最小分配单位为8字节,低于128字节(含128)的内存块申请,采用内存池分配策略,高于128字节的内存块申请,直接从操作系统new申请。转载 2024-01-09 22:46:24 · 438 阅读 · 0 评论 -
深入理解STL空间分配器(二):mt_allocator
templatepublic:// 用来构建_Thread_record链表,指向下一个_Thread_record节点,最后一个节点的_M_next指向null.// 该线程分配到的ID,从1到_S_max_threads.// 用来构建_Block_record链表,将内存块串联成链表形式// 请求该内存块的线程的ID// 指针数组,数组中的每个指针指向第一个空闲块节点,数组的大小等于线程的个数+1,每个线程占一个数组元素,0号表全局空闲链表// 内存块地址。转载 2024-01-09 22:39:25 · 315 阅读 · 0 评论 -
深入理解STL空间分配器(一): new_allocator
_new_allocator:C++标准中定义的分配器,仅对operator new和operator delete做简单封装;malloc_allocator:C++标准中定义的分配器,仅对std::malloc和std::free做简单封装;__mt_alloc:一种支持多线程的空间配置器(亦可单线程),可分配2的幂次方大小的内存块,该配置器可灵活调整,性能高(stl手册描述,个人未实测);bitmap_allocator:一种使用位图来区分内存是否分配的配置器;转载 2024-01-09 22:16:00 · 911 阅读 · 1 评论 -
C++内存分配策略
2.在栈上创建:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限,如数组,局部变量,形参。3.全局区(静态区、static): 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。一个可执行程序,在不运行时占用磁盘空间的是全局区、文字常量区和程序代码区,运行后栈区和堆区在内存里面才划分出来工作。原创 2024-01-08 22:29:08 · 1491 阅读 · 2 评论 -
深入理解可变参数(va_list、std::initializer_list和可变参数模版)
std::initializer_list 类型对象是一个访问 const T 类型对象数组的轻量代理对象。std::initializer_list 对象在这些时候自动构造:1)用花括号初始化器列表列表初始化一个对象,其中对应构造函数接受一个 std::initializer_list 参数,如std::vector的构造函数 vector(initializer_list _Ilist, const _Alloc& _Al = _Alloc())原创 2024-01-04 11:49:29 · 3499 阅读 · 0 评论 -
C/C++框架和库推荐
包括了STL容器,算法和函数等。:是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分。:标准模板库: POSIX系统的C标准库规范e :C++标准委员会。原创 2024-01-03 15:19:22 · 1579 阅读 · 1 评论 -
C++之数据转换(全)
截止C++20标准模板库同时提供了高级数值转换函数和低级数值转换函数,下面就仔细讲解一下这些数值转换函数的用法。原创 2023-12-23 12:44:40 · 2308 阅读 · 2 评论 -
C++高质量编程
这个是林锐博士整理出来的C++高质量编程指南,我写了十多年的代码,早期也是以这些经典资料为范本,经常阅读,对我的成长有很大的帮助。现在把它整理出来,希望对看到这边博客的人有所帮助。转载 2023-12-28 19:59:57 · 501 阅读 · 2 评论