cpp
图片来源:《灵笼》特别篇截图 方案一:继承 std::streambuf 详细解释查看 《C++标准库:第2版》 15.13章节 输出流(没有缓冲区) 在不考虑缓冲区的情况下,继承 std::streambuf 并重写两个函数 : 输出流(有缓冲区) 考虑缓冲区的话,需要: 输入流 输入流需要考虑支持回退(basic_istream& unget()),重写 virtual int_type underflow () 函数用以从文件描述符中读取数据到缓冲区,缓冲区前 4 字节保存可回退数据 方案二:使用 __gnu_cxx::stdio_filebuf stdio_filebuf 支持使用文件描述符或者C文件指针(std::__c_file * 即 FILE *)构造,部分构造函数: 使用示例: 注意:对于文件描述符,stdio_filebuf 在析构时会主动调用 close ;但对于 FILE * 则不会主动关闭,需要手动调用 fclose 方案三:使用 boost::iostreams::file_descriptor_source 和 boost::iostreams::file_descriptor_sink boost 的 file_descriptor_source 和 file_descriptor_sink 可以使用文件描述符来构造,继而构造出 boost::iostreams::stream ,部分构造函数: 其中 file_descriptor_source 只能从文件描述符读取数据,file_descriptor_sink 则只能写入数据,file_descriptor_flags 用以控制析构时是否自动关闭文件描述符 参考: 《C++标准库:第2版》 __gnu_cxx::stdio_filebuf< _CharT, _Traits >(3) —— man page File Descriptors —— boost
图片来源:https://www.pixiv.net/artworks/85222177 极简CMakeLists.txt 设置编译使用的C++标准 设置项目名称和版本 编译时自动生成包含版本号宏定义的头文件 添加INCLUDE路径 编译为静态库 链接库 让使用MathFunctions库的地方自动添加使用MathFunctions库必要的include路径 参考:
图片来源:https://www.pixiv.net/en/artworks/65883716 TL;DR 语法 含义 const T* 指向 const 对象的指针 T* const 指向对象的 const 指针 const T* const 指向 const 对象的 const 指针 吐槽“指针常量”和“常量指针” 这两个概念本身的含义都很简单,但所谓“指针常量”和“常量指针”的说法却将这两个概念理解和记忆难度成倍提升了。每当只看这两个中文,想要“顾名思义”的时候,我总会陷入混乱: 常量指针: 既可以理解为指向某个常量的指针(const T *),也可以理解为“常量”是对“指针”的修饰(T *const) 指针常量: 这个倒没什么歧义,像“整型常量”一样去理解就行,但定义语法看起来却又和整型常量完全不同:整形常量(const int), 指针常量(int *const) 当然如果只是以上这样,只要能做到概念统一的话那倒也没什么,权当我自己脑抽了,但好死不死《C++ Primer中文版(第5版)》里对这两个概念的英文直译又和百度百科里的定义完全相反 百度百科的定义 常量指针:const T * 指针常量:T * const 《C++ Primer》里的定义 指向常量的指针(pointer to const):const T * 常量指针(const pointer):T * const 另外,如果采用“指针常量”和“常量指针”的说法,当遇到“const T * const”时,是不是该叫“常量指针常量”😅(当然网上看到的说法大多为“指向常量的常指针”、“指向常量的指针常量”) 官方文档里的定义 当前的C++官方文档“指针声明”这一章的中文翻译里并没有上面这两个说法,取而代之的是“指向 const 对象的指针(pointer to constant object)”和“指向对象的 const 指针(constant pointer to object)” 指向 const 对象的指针:指针变量本身可以修改(即可以指向不同对象),但不能修改“指向的对象”里的内容(即对于指针p来说, “p = &a”可行,“*p = a”不可行) 指向对象的 const 指针:指针变量本身初始化后不可再修改(即不能指向其他对象),但可以修改“指向的对象”里的内容(即对于指针p来说, “p = &a”不可行,“*p = a”可行) 语法 含义 const T* 指向 const 对象的指针 T const* 指向 const 对象的指针 T* const 指向对象的 const 指针 const T* const 指向 const 对象的 const 指针 T const* const 指向 const 对象的 const 指针 指针声明语法 […]
图片来源:https://www.pixiv.net/artworks/72641025 Meyer’s Singleton 利用C++11保证静态局部变量初始化线程安全的特性 或许有用的模板实现 相对灵活,能够返回任意类型的固定对象指针,通过重载运算符略微增加复制语句的复杂度,但并不能阻止类型本身对象的复制 可以像这样复制T类型对象内容 参考:
图片来源:https://www.pixiv.net/artworks/101597578 大端序(网络序):高字节在低地址 小端序:高字节在高地址 判断当前运行环境的字节序 C++ 通过自定义变量值判断 另外,C++标准中对于结构体的非活跃成员的访问属于未定义行为,虽然使用g++编译运行都没问题,但以下代码不能保证运行结果正确 使用GCC宏 C++20标准库已经内置了字节序相关变量 Shell 输出“1”则为小端序,输出“0”则为大端序 查看CPU参数 CPU相关信息里的“Byte Order”字段有字节序信息 转换 Linux函数 Shell 反转字节序,输入输出均为十进制数 参考:
图片来源:https://www.pixiv.net/artworks/81470216 预备知识 算术右移 算术右移会保留符号位(或者填充符号位),这样可以保证左移一位等于除以2 ,算术上符合直觉;但如果只是观察bit位变化,对于负数来说,算术右移看起来就是不断在左边填充“1”,和其他位移操作相比,显得不那么符合直觉(无符号数左移/右移、正数算术左移/右移、负数算术左移都可以理解为填充“0”)。 C++ 20 明确规定了对于有符号数的右移为算术右移,C++ 20 前虽没明确规定,但大多编译器的实现上也是算术右移: For negative a, the value of a >> b is implementation-defined (in most implementations, this performs arithmetic right shift, so that the result remains negative). (until C++20) The value of a >> b is a/2b, rounded down (in other words, right shift on signed a is arithmetic right shift). (since C++20) Arithmetic operators 隐式类型转换 C++ 算术运算符不接受小于“int”的类型,所以位移运算前会把 signed char 转换成 int ,unsigned char 转换成 unsigned int 。观察bit位变化,对于无符号数和有符号正数来说,转换后额外bit位填充的是“0” ,对于负数来说转换后额外bit位填充的是“1”。 循环位移模板实现(C++ 20) 参考: