C/Cpp
文章平均质量分 55
介绍传统 Cpp 特性。
Ruo_Xiao
己所不欲,勿施于人。
展开
-
C/C++ / typeid 详解
【代码】C/C++ / typeid 详解。原创 2022-12-28 19:11:55 · 292 阅读 · 0 评论 -
__attribute__ format(printf, 1, 2) 的具体含义
format (printf, 2, 3) 告诉编译器,my_format 相当于 printf 的 format,而可变参数是从 my_printf 的第 3 个参数开始。这句主要作用是提示编译器,对这个函数的调用需要像 printf 一样,用对应的 format 字符串来检查可变参数的数据类型。这样编译器就会在编译时用和 printf 一样的检查法则来确认可变参数是否正确了。转载 2022-10-08 17:55:44 · 684 阅读 · 0 评论 -
理解可变参数 va_list、va_start、va_arg、va_end 原理及使用方法
其中,type 是指要获取的参数的类型,比如 int,char * 等,arg_ptr 是指向参数列表的指针(va_list类型),prev_param 是指最后一个显式声明的参数,以用来获取第一个变长参数的位置。比如 printf 函数,就是根据第一个参数推导可选实参:如果第一个'%'后有一个's',说明后面要有第二个参数,类型是字符串;大多数带有变长参数的函数都利用显式声明的参数中的一些信息,来获取调用中提供的其他可选实参的类型和数目。c)va_arg 返回变长参数的值,第二个参数是该变长参数的类型。转载 2022-10-08 17:52:10 · 483 阅读 · 0 评论 -
Cpp 11 / override 和 final 区别
一、override1、诞生原因C++ 中,有时继承关系较复杂时,基类和派生类各自的虚函数较多,导致开发人员傻傻地分不清哪些是重写了基类的虚函数,哪些是本派生类特有的虚函数。为了解决上述问题,添加了 virtual 描述符 override。2、作用该标识符表示开发人员与编译器产生约定:该标识符描述的函数必须是基类的虚函数,即:同名又同参,否则编译器无法通过。有了该关键字,派生类就可以分清哪些虚函数是重写了基类的虚函数,哪些虚函数是自己新建立的。3、注意该标识符不是关键字。二、f原创 2020-11-09 09:41:46 · 1206 阅读 · 0 评论 -
Cpp 11 / 线程库 / 可以做为线程的执行对象有哪些?
答案普通函数、仿函数、lambda 表达式栗子#include <iostream>#include <thread>class CTest{public: // 仿函数。 void operator()() { std::cout << " () " << std::endl; ...原创 2020-03-03 20:25:25 · 201 阅读 · 0 评论 -
C++11 std::function
@time 2019-07-07@author Ruo_Xiao1、头文件#include <functional>2、作用 类模版std::function是一种通用、多态的函数封装,形成一个新的可调用的std::function对象。std::function的实例可以对任何可以调用对象进行存储、复制和调用操作。std::function...原创 2019-07-07 22:15:17 · 1662 阅读 · 0 评论 -
C++中,有哪4种与类型转换相关的关键字?各有什么特点?应该在什么场合下使用?
C++中,四个与类型转换相关的关键字:static_cast、const_cast、reinterpret_cast、dynamic_cast。一、static_cast特点:静态转换,在编译处理期间。应用场合:主要用于 C++ 中内置的基本数据类型之间的转换,但是没有运行时类型的检测来保证转换的安全性。用于基类和子类之间的指针或引用之间的转换,这种转换把子类的指针或引用转换为基类表示是安全的;进行下行转换,把积累的指针或引用转换为子类表示时,由于没有进行动态类型检测,所以是不安全的。 把转载 2021-05-07 06:41:31 · 471 阅读 · 0 评论 -
Cpp / 通用引用、引用折叠与完美转发问题
一、通用引用通用引用,允许其绑定右值(就像右值引用那样)和左值(就像左值引用那样)。而且,它们可以绑定 const 或者非 const 对象,可以绑定 volatile 和非 volatile 对象,还可以绑定 const 和 volatile 同时作用的对象。它们实际上可以绑定任何东西。构成通用引用有两个条件: 必须精确满足 T&& 这种形式(即使加上 const 也不行) 类型T必须是通过推断得到的(最常见的就是模板函数参数) 二、引用折叠引用折叠规则:X转载 2021-04-07 10:30:17 · 412 阅读 · 0 评论 -
Cpp / #error、static_assert、assert 区别
一、#error执行期间是预编译阶段,目的是配合 #ifdef / #ifndef 参与预编译的条件检查,显示一段错误信息。二、static_assertstatic_assert(bool flag, char *msg);编译期断言,程序在编译的过程中执行。 若 flag 为真,什么也不做。 若 flag 为假,产生一条编译错误,输出错误信息 msg,错误位置为当前行号。static_assert 可以放在代码中任何位置,可以增加编译期对程序的控制,准确定位出错的可能。三、a原创 2021-05-19 09:21:13 · 334 阅读 · 0 评论 -
Cpp / 右值、纯右值、将亡值
一、左值与右值左值(lvalue)和右值(rvalue)是 C++ 类型系统之中的基础概念,我们不需要了解这些基础概念,同样也能写出代码。但是如果没有弄清左右值的概念,对于许多 C++ 高级特性的探索会一叶障目,所以笔者尝试总结一下自己对于左值与右值的理解。在 C++11 之前的版本,基本沿用了 C 语言之中对于左值与右值的定义,说起来也很简单:“在C++之中的变量只有左值与右值两种:其中凡是可以取地址的变量就是左值,而没有名字的临时变量,字面量就是右值”。 正是因为这两种变量分别位于 = 的左右两转载 2021-04-06 20:43:13 · 3592 阅读 · 0 评论 -
Cpp / shared_ptr 配置删除器的方法
一、普通函数void Deleter(T *x){ delete[] x;}std::shared_ptr<T> p1(new T[5], Deleter);二、仿函数class Deleter{public: void operator() (T *x) { delete[] x; }};std::shared_ptr<T> p2(new T[5], Deleter);三、lamda 表达式std::shared_ptr<原创 2020-11-22 07:40:45 · 848 阅读 · 0 评论 -
Cpp / checked_delete 原理
看智能指针的时候遇到一组函数蛮有意思的,即checked_delete(T* x)和checked_array_delete(T* x),这两个函数的作用是安全删除参数所指向的变量或数组。[cpp] view plain copytemplate<classT>inlinevoidchecked_delete(T*x) { typedefchartype_must_be_complete[sizeof(T)?1:-1]; (...转载 2021-03-17 09:53:07 · 167 阅读 · 0 评论 -
Cpp / shared_ptr
1、诞生原因在 C++ 中,一大缺陷是给定一个非空指针,程序并不能确定该指针指向的内存是否正常,即:是否已经被释放掉。为了解决上述问题,boost 库中诞生了 shared_ptr 智能指针。2、核心思想shared_ptr 智能指针设计的核心思想是对内存块采用引用计数的方式进行内存回收,每增加一个 shared_ptr 对该内存块的指向,则引用计数 + 1,否则 - 1,当引用计数为 0 时则 delete 该内存块。3、栗子#include <iostream>#原创 2020-11-10 22:01:06 · 399 阅读 · 0 评论 -
Cpp / 无锁编程
无锁编程,就是编译器不再使用系统中关于锁的 API,而是直接通过使用缓存一致性等算法达到锁的目的的一种编程。可以使用 std::atomic<T> 系列和 __sync_val_compare_and_swap 系列均是无锁编程的体现。栗子:#include <iostream>#include <thread>#include <mutex>#include <atomic>#include <chrono>原创 2021-05-06 14:19:39 · 220 阅读 · 0 评论 -
C++11 std::bind 和 std::placeholder
@time 2019-07-07@author Ruo_Xiao一、std::functionhttps://blog.csdn.net/itworld123/article/details/95034012二、std::bind1、函数原型 template<typename _Result, typename _Func, typename... _B...原创 2019-07-07 22:35:53 · 4034 阅读 · 1 评论 -
Cpp / std::move 原理
零、功能和源码std::move 是一个类型转换器,将左值转换成右值,其实现如下:template <typename T>typename remove_reference<T>::type&& move(T&& t){ return static_cast<typename remove_reference<T>::type&&>(t);}std::move 的实现还是挺简单的就转载 2021-04-07 10:07:35 · 2062 阅读 · 2 评论 -
shared_ptr 循环引用问题以及解决办法
栗子#include <iostream>#include <memory>class CB;class CA{public: CA() { std::cout << "CA() called! " << std::endl; } ~CA() { std::cout << "~CA() called! "...转载 2020-02-26 08:06:18 · 1443 阅读 · 2 评论 -
Cpp 11 / 万能引用、引用折叠和完美转发
一、万能引用1、英文:Universal Reference 。2、诞生的原因因为 C++ 中存在左值引用和右值引用,导致若想同时实现既可传入左值又可传入右值的功能,需要对相同函数进行重载,导致代码冗余。3、解决办法为了解决上述问题,就诞生了万能引用,具体用法如下:template<typename T>void func(T&& param) { ;}主要实现方法是依靠 C++ 强大的模板推导能力,在编译期间确定 param 是左值.原创 2020-12-09 07:36:55 · 1772 阅读 · 0 评论 -
Cpp / __builtin_expect 说明
__builtin_expect 主要用于 if 判断语句中,功能是让程序员告诉编译器,哪一个分支最有可能执行。一般使用方法是将 __builtin_expect 指令封装为 likely 和 unlikely 宏。这两个宏的写法如下:#define likely(x) __builtin_expect(!!(x), 1) // x 很可能为真 #define unlikely(x) __builtin_expect(!!(x), 0) // x 很可能为假(SAW:Gam.原创 2021-05-20 10:18:17 · 143 阅读 · 0 评论 -
请实现一个函数,将字符串中的空格替换成“%20”
一、传统做法从开始位置向后遍历,如果发现空格,则挪动后面的字符串腾出 2 个字符的空间,写入“%20”,直至到字符串末尾。(灰色部分是每次要挪动的字符)这种方法非常直观,但是性能较差。假设字符串长度为 n,其中空格数量为 m,那么时间复杂度大概为 O(m*n),简化为 m = n,那么时间复杂度就变成了 O(n^2) 。二、高性能做法为了提高性能,需要尽可能的减少后面字符不必要的挪动次数,即:最后一次就能将后面的字符挪动到最终的位置上,方法就是从后面开始遍历字符串。为了达到上述目原创 2021-05-15 13:38:00 · 668 阅读 · 0 评论 -
Cpp / std::string 实现
一、答案#include <iostream>#include <string.h>#include <assert.h>class String{public: String(const char *str = nullptr); String(const String &other); ~String(void); String &operator=(const String &other);原创 2021-05-07 09:18:13 · 379 阅读 · 0 评论 -
Cpp / 拷贝构造函数的参数为什么必须使用引用类型
表面原因:编译器无法通过,会报如下错误:error: invalid constructor; you probably meant ‘CExample (const CExample&)’ CExample(CExample ex) //拷贝构造函数深层次原因是避免拷贝构造函数无限制的递归下去。栗子:#include <iostream>class CExample{ int m_nTest;public: CExample(i.原创 2021-05-07 07:05:09 · 157 阅读 · 0 评论 -
c/c++ / printf 实现
一、源码实现#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <assert.h>void my_printf(const char *fmt, ...){ va_list ap; va_start(ap, fmt); /* 用最后一个具有参数的类型的参数去初始化ap */ for (; *fmt; ++fmt) {原创 2021-05-06 09:14:54 · 966 阅读 · 0 评论 -
Cpp / 空指针对象调用函数的不同结果
今天被问到如下问题:CA *p = nullptr;p->test();会有什么结果。实际上不同的成员函数会有不同的情况,经过测试如下:#include <iostream>class CA{public: static void s_fun() {} virtual void v_fun() {} void fun1() {} void fun2() { i = 2; }private: int i = 0;};原创 2021-04-09 11:41:16 · 323 阅读 · 0 评论 -
C/C++ 使用 C 语言实现多态
#include <stdio.h>typedef void (*PF_Fun)(); typedef struct MyBase1_t{ int k; PF_Fun m_pf_fun;} MyBase1;typedef struct MyBase2_t{ PF_Fun m_pf_fun;} MyBase2;typedef struct MyDerived_t{ MyBase1 _b1; MyBase2 _b2;} MyDer.原创 2021-04-01 07:17:50 · 219 阅读 · 0 评论 -
do{...}while(0) 的意义和用法
linux内核和其他一些开源的代码中,经常会遇到这样的代码:do{ ...}while(0)这样的代码一看就不是一个循环,do..while 表面上在这里一点意义都没有,那么为什么要这么用呢?实际上,do{...}while(0) 的作用远大于美化你的代码。查了些资料,总结起来这样写主要有以下几点好处:1、辅助定义复杂的宏,避免引用的时候出错举例来说,假设你需要定义这样一个宏:#define DOSOMETHING()\ foo1();\转载 2021-03-17 21:26:27 · 220 阅读 · 0 评论 -
Cpp / 引用的本质
一、答案一个指针变量,即:T *const 。二、分析 int a = 0; int &b = a; int c = 3; int *p = &c; b = *p; int a = 0;009925F2 mov dword ptr [a],0 ; *(&a) = 0 int& b = a;009925F9 lea eax,[a] ; eax = &原创 2020-12-08 15:23:04 · 129 阅读 · 0 评论 -
测试 / 单元测试的重要性
一、什么是单元测试?要搞懂单元测试,首要要弄清楚什么是单元。单元是软件中承担单一责任的单位,一个函数、一个文件、一个类、一个模块都可以称为一个单元。单元测试便是对软件设计的最小单位进行正确性测试,以检验程序单元是否满足功能、性能、接口、设计规约等要求。单元测试本质上也是代码,与普通代码的区别在于它是验证代码正确性的代码。软件开发天生就具有复杂性,没人敢打包票说自己写的代码一点问题都没有,或者不经测试就能保证代码正确运行,可能你在这个执行路径下能够执行,殊不知还有其他路径,有一一去验证过吗?转载 2020-12-01 22:13:31 · 992 阅读 · 0 评论 -
C/Cpp / 参数传递时如何防止数组退化为指针
一、答案函数参数使用数组引用。二、栗子#include <iostream>void print_1(int data[4]){ std::cout << sizeof(data) << std::endl; for (int i = 0; i < 4; i++) std::cout << data[i] << " "; std::cout << std::endl;}原创 2020-11-20 12:12:31 · 629 阅读 · 0 评论 -
C/Cpp / 野指针和悬空指针
一、定义野指针(Wild Pointer):没有初始化的指针。 悬空指针(Dangling Pointer):指向的内存已经释放。二、危害由于指向的是不安全不可控的区域,任何情况都有可能发生,比如:崩溃、执行结果错误、系统崩溃等。三、如何避免传统方法:每一个指针必须初始化为 null,可以避免 野指针 的产生。但是对于悬空指针来说就比较难处理,只能每次 delete 内存之后将指针置为 null,但是其他指向该内存的指针如果有遗漏没有置为 null 的则很容易造成悬空指针。现代C++原创 2020-11-11 07:56:36 · 441 阅读 · 1 评论 -
Cpp / STL / map 插入和删除元素的三种方式
#include <map>#include <iostream>void print(const std::map<std::string, int> &m){ if (m.size() == 0) { std::cout << "null" << std::endl; } for (auto it : m) { std::cout << "ke.原创 2020-11-10 17:38:08 · 809 阅读 · 0 评论 -
C/Cpp / string 截取、替换、查找
1. 截取函数 详解 s.substr(pos, n) 截取 s 中从 pos 开始(包括0)的 n 个字符的子串,并返回。 s.substr(pos) 截取 s 中从 pos 开始(包括0)到末尾的所有字符的子串,并返回。 2. 替换函数 详解 s.replace(pos,n,s1) 用 s1 替换 s 中从 pos 开始(包括0)的 n...原创 2020-02-28 12:23:02 · 881 阅读 · 0 评论 -
判断系统是大端字节序还是小端字节序的C代码
#include <iostream>int main(){ short int i = 0x0102; char *pc = (char *)&i; if (pc[0] == 1) { std::cout << "big endian" << std::endl; } else ...原创 2020-02-12 09:02:09 · 170 阅读 · 0 评论 -
进程有一个全局变量 i,还有有两个线程。i++ 在两个线程里边分别执行 100 次,能得到的最大值和最小值分别是多少?
转自https://blog.csdn.net/biubiu741/article/details/77990592多核CPU最小值为2,最大值200假设两个线程的执行步骤如下: 1. 线程A执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU1的寄存器中值为1,内存中为0; 2. 线程B执行第一次i++,取出内存中的i,值...转载 2020-02-10 21:30:45 · 766 阅读 · 0 评论 -
C/Cpp / typeof、_typeof 和 _typeof_ 区别和联系
功能类似于 Cpp 中的 decltype ,用于推导该变量或者常量的数据类型。栗子#include <iostream>int main(){ typeof(12) i = 10; std::cout << i << std::endl; return 0;}结果为 1 。区别typeof、_typeof...原创 2020-02-04 11:22:51 · 1120 阅读 · 0 评论 -
C/Cpp / 类的前向声明、不完全类型和完全类型
1、类的定义和声明也可以像函数一样分开。栗子:class CSys;上述声明被称为前向声明。对于CSys来说,其声明之后和定义之前,被称为不完全类型。2、不完全类型的使用场景极其有限:(1)定义指向该类型的指针和引用。(2)声明(不能定义)以不完全类型作为参数和返回值的函数。3、完全类型:类不光已经声明,而且完成了定义。4、拓展:类中不可以定义类本身,但是可以声明类自身...原创 2020-02-03 10:32:26 · 659 阅读 · 0 评论 -
C/Cpp / const 用法
修饰变量,表示该变量为常变量,可代替宏。 修饰指针,表示该指针,表示该指针指向常量或者该指针为常指针。 修饰引用,常用于修饰函数形参,变成常引用,可以避免重复拷贝和函数对值的修改。详细说明:https://blog.csdn.net/itworld123/article/details/78967080修饰函数,表示该函数不能对类成员变量进行修改。 修饰函数返回值,如下所示:con...原创 2020-01-20 10:34:11 · 336 阅读 · 0 评论 -
C/Cpp / 类中静态成员变量和普通成员变量的区别
2017-12-11 创建人:Ruo_Xiao实例代码:#include <iostream>class CMan{public: CMan() {} ~CMan() {}public: int k_; // 仅仅是声明。 static int i_;};// 定义,申请内存。int CMan::i_ = 0;int main(){ ...原创 2019-11-22 11:48:44 · 1181 阅读 · 0 评论 -
C/Cpp / 构造函数种类
2018-03-15 创建人:Ruo_Xiao开发环境:VS2010邮箱:xclsoftware@163.com2018-04-16 修改人:Ruo_Xiao添加对类型转换构造函数隐式转换的抑制使用的说明,即:explicit。2019-06-19 修改人:Ruo_Xiao修正对转换构造函数的说明。一、默认构造函数(无参数构造函数)Father(){ s...原创 2019-11-15 17:09:08 · 343 阅读 · 0 评论 -
#pragma once与#ifndef的区别?
#prama once和#ifndef的区别原创 2017-12-20 15:52:48 · 404 阅读 · 0 评论