本文最后更新于 2024-11-25,文章内容可能已经过时。

sizeof 是 C 和 C++ 编程语言中的一个操作符,用于计算数据类型或变量在内存中所占的字节数。它是一个编译时操作符,这意味着它在程序编译时就被计算出来,而不是在运行时。
sizeof 可以应用于基本数据类型(如 int, char, float 等)、数组、结构体、联合体以及指针等。其语法如下:

  • sizeof(type):计算指定类型 type 所占用的字节数。
  • sizeof variable:计算变量 variable 所占用的字节数。
  • sizeof(array):对于数组,sizeof 返回整个数组所占用的字节数。
  • sizeof(structure)sizeof(union):对于结构体或联合体,sizeof 返回它们所占用的最大字节数(注意,由于对齐的原因,实际占用的字节数可能会大于各成员所需字节数之和)。
#include <iostream>
using namespace std;

int main() {
    long long money = 100;
    cout << "long long变量在内存中所占的字节数:" << sizeof(long long) << endl;
    cout << "long long变量在内存中所占的字节数:" << sizeof(money) << endl;
    return 0;
}
//long long变量在内存中所占的字节数:8
//long long变量在内存中所占的字节数:8

一、基本数据类型

Ⅰ、整型

  • char:通常用于存储字符,但在技术上它是一个整数类型。
  • int:用于存储整数。
  • short int:短整型,占用空间比 int 小。
  • long int:长整型,占用空间比 int 大。
  • long long int:更长的整型,占用的空间比 long int 更大。
数据类型占用空间取值范围
short(短整型)2字节(-2^15 ~ 2^15-1)
int(整型)4字节(-2^31 ~ 2^31-1)
long(长整形)Windows为4字节, Linux为4字节(32位), 8字节(64位)(-2^31 ~ 2^31-1)
long long(长长整形)8字节(-2^63 ~ 2^63-1)

Ⅱ、浮点型

  • float:单精度浮点数。
  • double:双精度浮点数,比 float 精度更高。
  • long double:扩展精度浮点数,比 double 精度更高。

Ⅲ、布尔型

  • bool:用于表示真(true)或假(false)。

Ⅳ、空类型

  • void:表示没有类型,通常用于函数返回值,当函数不返回任何值时使用。

二、派生数据类型

Ⅰ、指针

  • 例如:int* 表示指向 int 类型的指针。

Ⅱ、数组

  • 例如:int arr[10] 表示包含10个整数的数组。

Ⅲ、结构体和联合体

  • 结构体允许将不同类型的数据组合在一起。
  • 联合体类似于结构体,但是所有成员共享同一块内存位置。

Ⅳ、枚举

  • 例如:enum Color {RED, GREEN, BLUE}; 定义了一个颜色枚举。

三、复合数据类型

  1. 类和对象
    • 类是用户定义的数据类型,用于封装数据和操作这些数据的方法。
    • 对象是类的实例。

四、类型修饰符

  1. signedunsigned
    • 可以用来指定整数类型是否包含负数。
      • 例如:unsigned int 表示非负整数。
  2. shortlong
    • 用于改变整数类型的大小。
      • 例如:short intlong int

五、高级数据类型和概念

1、自动类型推导

  • auto:从初始化表达式中自动推导变量的类型。

    auto x = 42; // x 的类型为 int
    auto y = 3.14; // y 的类型为 double
    
  • decltype:从表达式中推导类型。

    int x = 42;
    decltype(x) y = 10; // y 的类型为 int
    

2、引用类型

  • 引用(References):引用是变量的别名,必须在声明时初始化,并且不能重新绑定到另一个变量。

    int x = 42;
    int& ref = x; // ref 是 x 的引用
    ref = 10; // x 的值变为 10
    

3、常量类型

  • const:用于声明常量,表示该变量的值在声明后不能被修改。

    const int x = 42; // x 是一个常量
    
  • constexpr:用于声明编译时常量,可以在编译时计算结果。

    constexpr int square(int x) {
        return x * x;
    }
    constexpr int y = square(5); // y 的值在编译时计算为 25
    

4、可变类型

  • mutable:用于类中的成员变量,即使类的对象被声明为 const,该成员变量仍然可以被修改。

    class MyClass {
    public:
        mutable int count;
        void increment() const {
            ++count; // 即使对象是 const 的,也可以修改 count
        }
    };
    

5、空指针

  • nullptr:表示空指针常量,替代传统的 NULL0

    int* ptr = nullptr; // ptr 是一个空指针
    

6、范围类型

  • std::pairstd::tuple:用于组合多个不同类型的值。

    std::pair<int, std::string> p(42, "answer");
    std::tuple<int, double, char> t(42, 3.14, 'A');
    

7、智能指针

  • std::unique_ptrstd::shared_ptrstd::weak_ptr:用于管理动态分配的内存,提供自动资源管理。

    std::unique_ptr<int> ptr1(new int(42)); // 独占所有权
    std::shared_ptr<int> ptr2(new int(42)); // 共享所有权
    std::weak_ptr<int> ptr3 = ptr2; // 弱引用
    

8、模板元编程

  • 模板(Templates):用于实现泛型编程,可以在编译时生成特定类型的代码。

    template <typename T>
    T max(T a, T b) {
        return (a > b) ? a : b;
    }
    

9、类型别名

  • typedefusing:用于为现有类型创建别名。

    typedef unsigned int uint;
    using uint = unsigned int;
    

10、类型转换

  • static_castdynamic_castconst_castreinterpret_cast:用于在不同类型之间进行安全或不安全的类型转换。

    int x = 42;
    double y = static_cast<double>(x); // 显式类型转换
    
    #include <iostream>
    using namespace std;
    
    constexpr int square(int x) {
        return x * x;
    }
    
    int main() {
        int x = 42;
        auto y = static_cast<double>(x); // 显式类型转换
        cout << square(x) << endl;
        cout << y << endl;
        cout << sizeof(x) << endl;
        cout << sizeof(y) << endl;
        return 0;
    }
    

六、标准库类型

C++ 标准库提供了许多有用的类型和容器

1、字符串

  • std::string:用于处理文本字符串。

    std::string str = "Hello, World!";
    

2、容器

  • 序列容器
    • std::vector:动态数组。
    • std::list:双向链表。
    • std::deque:双端队列。
  • 关联容器
    • std::setstd::multiset:集合,元素唯一或可重复。
    • std::mapstd::multimap:键值对映射,键唯一或可重复。
  • 无序关联容器
    • std::unordered_setstd::unordered_multiset:哈希集合,元素唯一或可重复。
    • std::unordered_mapstd::unordered_multimap:哈希映射,键唯一或可重复。

3、迭代器

  • 用于遍历容器中的元素。

    std::vector<int> vec = {1, 2, 3, 4, 5};
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    

七、算法

C++ 标准库提供了大量的算法,用于处理容器中的数据

1、排序

  • std::sort:对容器中的元素进行排序。

    std::vector<int> vec = {5, 3, 4, 1, 2};
    std::sort(vec.begin(), vec.end());
    

2、查找

  • std::find:在容器中查找某个元素。

    auto it = std::find(vec.begin(), vec.end(), 3);
    if (it != vec.end()) {
        std::cout << "Found: " << *it << std::endl;
    }
    

3、变换

  • std::transform:对容器中的元素应用某个函数。

    std::vector<int> vec1 = {1, 2, 3, 4, 5};
    std::vector<int> vec2(vec1.size());
    std::transform(vec1.begin(), vec1.end(), vec2.begin(), [](int x) { return x * 2; });
    

八、异常处理

C++ 提供了异常处理机制,用于处理程序运行时可能出现的错误

1、抛出异常

  • throw:用于抛出异常。

    throw std::runtime_error("An error occurred!");
    

2、捕获异常

  • trycatch:用于捕获并处理异常。

    try {
        // 可能会抛出异常的代码
        throw std::runtime_error("An error occurred!");
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }
    

九、内存管理

C++ 提供了多种内存管理机制,包括动态内存分配和释放

1、动态内存分配

  • newdelete:用于动态分配和释放内存。

    int* ptr = new int(42);
    delete ptr;
    

2、智能指针

  • std::unique_ptrstd::shared_ptrstd::weak_ptr:用于自动管理动态分配的内存。

    std::unique_ptr<int> ptr1(new int(42));
    std::shared_ptr<int> ptr2(new int(42));
    std::weak_ptr<int> ptr3 = ptr2;
    

十、多线程(Multithreading)

C++11 引入了多线程支持,使得并发编程变得更加容易

1、线程

  • std::thread:用于创建和管理线程。

    #include <thread>
    void thread_func() {
        // 线程函数
    }
    int main() {
        std::thread t(thread_func);
        t.join();
        return 0;
    }
    

2、互斥锁(Mutexes)

  • std::mutex:用于保护共享资源。

    #include <mutex>
    std::mutex mtx;
    void critical_section() {
        std::lock_guard<std::mutex> lock(mtx);
        // 临界区代码
    }
    

十一、文件输入输出(File I/O)

C++ 提供了文件输入输出的支持,用于读写文件

1、文件流

  • std::ifstream:用于读取文件。
  • std::ofstream:用于写入文件。
  • std::fstream:用于读写文件。
#include <fstream>
void read_file(const std::string& filename) {
    std::ifstream file(filename);
    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << std::endl;
    }
}

十二、模板元编程(Template Metaprogramming)

模板元编程是一种在编译时执行计算的技术,可以生成高效的代码。

1、模板特化

  • 用于为特定类型提供不同的实现。

    template <typename T>
    struct MyType {
        static const bool value = false;
    };
    
    template <>
    struct MyType<int> {
        static const bool value = true;
    };
    

2、递归模板

  • 用于在编译时进行递归计算。

    template <int N>
    struct Factorial {
        static const int value = N * Factorial<N-1>::value;
    };
    
    template <>
    struct Factorial<0> {
        static const int value = 1;
    };
    

十三、属性

C++11 引入了属性,用于向编译器提供额外的信息,影响编译行为

1、常用的属性

  • [[nodiscard]]:建议编译器警告未使用的返回值。

  • [[deprecated]]:标记过时的函数或类型。

    [[nodiscard]] int important_function() {
        return 42;
    }
    
    [[deprecated("Use new_function instead")]] void old_function() {
        // 旧函数实现
    }
    

十四、模块

C++20 引入了模块,用于替代头文件,提高编译效率和代码组织

1、模块单元

  • module:定义模块。

  • import:导入模块。

    // math.ixx
    export module math;
    
    export int add(int a, int b) {
        return a + b;
    }
    
    // main.cpp
    import math;
    
    int main() {
        int result = add(2, 3);
        std::cout << "Result: " << result << std::endl;
        return 0;
    }
    

十五、总结

C++ 设计多种数据类型的主要原因是为了提供灵活性、效率和安全性。

1. 灵活性

  • 适应不同的应用场景:不同的应用领域对数据的需求各不相同。例如,处理图像像素时通常需要8位无符号整数(unsigned char),而科学计算可能需要高精度的浮点数(double)。多种数据类型能够更好地满足这些不同的需求。
  • 用户自定义类型:通过结构体、类等自定义类型,开发者可以根据具体需求创建复杂的数据结构,提高代码的可读性和可维护性。

2. 效率

  • 内存优化:不同数据类型占用的内存大小不同。例如,char 占用1个字节,而 int 通常占用4个字节。合理选择数据类型可以减少内存消耗,提高程序的运行效率。
  • 性能优化:不同类型的数据在进行运算时有不同的性能表现。例如,整数运算通常比浮点数运算更快。选择合适的数据类型可以提高计算速度。

3. 安全性

  • 类型检查:C++ 编译器会在编译阶段进行严格的类型检查,确保不同类型的数据不会被错误地混用。这有助于减少运行时错误,提高程序的健壮性。
  • 避免溢出:不同大小的整数类型(如 intlonglong long)可以帮助开发者更好地管理数值范围,避免因溢出导致的错误。

4. 表达能力

  • 语义清晰:不同的数据类型可以更准确地表达数据的含义。例如,使用 bool 类型可以明确表示逻辑值,使用 enum 类型可以定义一组相关的常量,使代码更具可读性。
  • 代码规范:合理的类型使用可以遵循编码规范,提高代码的质量和一致性。

5. 兼容性和扩展性

  • 兼容性:C++ 作为一种广泛使用的编程语言,需要支持各种硬件平台和操作系统。多种数据类型可以更好地适应不同平台的特性。
  • 扩展性:随着技术的发展,新的数据类型和需求不断出现。C++ 的类型系统设计允许添加新的数据类型,如 std::stringstd::vector 等标准库中的类型,以及用户自定义的复杂类型。