C++右值

在C++98时代,我们经常会遇到这样的性能瓶颈:当需要返回或传递大型对象(如字符串、向量或自定义资源管理类)时,不得不进行昂贵的深拷贝操作。即使我们知道某些对象即将被销毁,也无法避免这种拷贝开销。 C++11引入的右值引用和移动语义彻底改变了这一局面,让C++程序员能够写出更高效、更现代的代码。

C++语言

C++智能指针

C++从C++11开始引入了智能指针(std::unique_ptr、std::shared_ptr、std::weak_ptr),并后面的各个版本中对智能指针进行了改进。

C++语言

从C++11开始新增的常用关键字

nullptr (C++11)nullptr 专门用于表示空指针,旨在解决传统 NULL 或 0 在类型安全性和代码清晰度上的缺陷。 nullptr 的类型为 std::nullptr_t,只能隐式转换为指针类型(包括原生指针、智能指针、托管句柄等),​不能转换为整数类型,避免了与整型 0 的混淆。 而传统 NULL 是宏(通常定义为 0 或 (void*)0),可能被误解释为整数,导致类型错误。

C++语言

C99柔性数组

在讲述柔性数组(Flexible Array)之前,首先要介绍一下不完整类型 (Incomplete Type)。不完全类型是暂时没有完全定义好的类型,缺乏足够的信息(例如长度、类型)去描述一个完整的类型。在C/C++中不完全类型有三种不同形式:void、未指定长度的数组以及具有非指定内容的结构和类。

C++语言

C++异常之我所见

C++异常所带来的问题当我们在代码中写下一行 throw 语句时,我们就此埋下了一个祸根,从此以后,在该函数调用链中,必须至少有一个调用者需要提供相应的异常捕获,否则一旦异常被抛出,程序就会异常终止。 例如,函数 f() 调用 g(),而 g() 又调用 h(),并且 h() 抛出一个异常,则 g() 和 f()中必须有一个提供了相应的异常捕获,否则程序会异常终止。 由于异常会使代码的执行流程从任意地方跳出,因此我们还需要付出大量的精力来编写正确的异常安全代码,例如使用 RAII(资源获取即初始化)来保证资源正确释放。 如下面的示例,虽然我们在函数 f() 中捕获了异常,避免了程序的异常终止,但异常却中断了函数 g() 的正常执行流程,导致对象 m 没有被正确释放,从而出现了资源泄露。这种情况可能还会变相地增加了程序的调试难度。

C++语言

如何通过结构体成员地址获取父地址

有如下结构体: 12345678struct Test { int a; // .... // 还有若干成员 // ... int y; int z;}; 在只知道成员变量y地址的情况下,如何获取到结构体的首地址?

C++语言

ABI兼容性

ABI 是 Application Binary Interface 的缩写,当我们以二进制形式(非源码形式)发布我们的动态库时,就需要关心ABI兼容(也称二进制兼容)。 对于静态库,更新静态库始终都需要该库的使用方重新编译,因此不存在ABI兼容的说法。

C++语言

C/C++不同整数类型的区别

在C/C++中涉及的整数相关的类型大致有如下几种: char、unsigned char short、unsigned short int、unsigned int long、unsigned long long long、unsigned long long int8_t、uint8_t int32_t、uint32_t int64_t、uint64_t DWORD DWORD32、DWORD64 size_t、ssize_t SIZE_T、SSIZE_T

C++语言

MSVC版本的二进制兼容性

Visual Studio 2013 及更早版本中的 Microsoft C++ (MSVC) 编译器工具集不保证主版本间的二进制兼容性,无法链接由不同版本工具集生成的对象文件、静态库、动态库和可执行文件,因为ABI、对象格式和运行时库不兼容。 微软在 Visual Studio 2015 及更高版本中改变了这个行为。对于自 Visual Studio 2015 以来的所有版本(该版本号都以 14 开头,如Visual Studio 2015、2017、2019 和 2022工具集的版本分别为 v140、v141、v142 和 v143)由其中任一版本编译器编译的运行时库和应用都具有二进制兼容性。 假设你使用 Visual Studio 2015 生成第三方库,你仍可在 Visual Studio 2017、2019 或 2022 生成的应用程序中使用它们,无需使用匹配工具集重新编译。 同时最新版本的 Microsoft Visual C++ 可再发行程序包(运行时库)也兼容所有老版本,无需为不同版本安装不同的运行时库,统一安装最新版本即可。

C++语言

C++字符串和字符字面量

C++ 支持各种字符串和字符类型,并提供了表达每种类型字面值的方法。在源代码中,我们使用字符集来表示字符或字符串。同时我们还可以使用通用字符名和转义字符来通过基本的源字符集表示任何字符串。而原始字符串能够避免对转义字符进行转义,并可用于表示所有类型的字符串。

C++语言

LLVM-Obfuscator代码混淆

LLVM-Obfuscator 可用于混淆程序的代码逻辑,本文介绍如何使用 LLVM-Obfuscator 进行代码逻辑的混淆。

C++语言

C++构造函数排雷

一、默认构造函数1.1 什么是默认构造函数?我们一般会认为默认构造函数就是编译器自动生成的那个构造函数,其实这种理解不全面。准确的说,默认构造函数就是在调用时不需要显示地传入实参的构造函数。根据这个原则,下面 2 种构造函数都是默认构造函数: 1234567class Sample {public: // 默认构造函数。 Sample() { // do something }}; 1234567class Sample {public: // 默认构造函数。虽然有形参,但有默认值,调用时可以不显式地传入实参。 Sample(int m = 10) { // do something }};

C++语言
12