C++ 数据类型完全指南

一、基本内置数据类型

1. 整型(Integer Types)

#include <iostream>
#include <climits>
using namespace std;
 
int main() {
    // 基本整型
    int a = 42;                  // 通常为4字节,范围:-2^31 到 2^31-1
    short b = 100;               // 通常为2字节,范围:-32768 到 32767
    long c = 100000L;            // 至少4字节
    long long d = 10000000000LL; // 至少8字节(C++11)
    
    // 无符号整型
    unsigned int ua = 42U;
    unsigned short ub = 100;
    unsigned long uc = 100000UL;
    unsigned long long ud = 10000000000ULL;
    
    // 查看类型大小和范围
    cout << "int: " << sizeof(int) << " bytes" << endl;
    cout << "int range: " << INT_MIN << " to " << INT_MAX << endl;
    cout << "long long: " << sizeof(long long) << " bytes" << endl;
    cout << "long long range: " << LLONG_MIN << " to " << LLONG_MAX << endl;
    
    return 0;
}

2. 字符型(Character Types)

#include <iostream>
using namespace std;
 
int main() {
    // 基本字符类型
    char ch1 = 'A';              // 1字节,ASCII字符
    char ch2 = 65;               // 可以用数字表示
    signed char sch = -100;      // 明确指定有符号
    unsigned char uch = 200;     // 明确指定无符号
    
    // 宽字符类型
    wchar_t wch = L'中';         // 宽字符,通常2或4字节
    char16_t ch16 = u'A';        // 16位Unicode字符(C++11)
    char32_t ch32 = U'😀';       // 32位Unicode字符(C++11)
    char8_t ch8 = u8'A';         // UTF-8字符(C++20)
    
    // 字符串字面量
    const char* str1 = "Hello";           // C风格字符串
    const wchar_t* str2 = L"你好";        // 宽字符串
    const char16_t* str3 = u"Hello";      // UTF-16字符串
    const char32_t* str4 = U"Hello";      // UTF-32字符串
    const char8_t* str5 = u8"Hello";      // UTF-8字符串(C++20)
    
    cout << "char size: " << sizeof(char) << " byte" << endl;
    cout << "wchar_t size: " << sizeof(wchar_t) << " bytes" << endl;
    
    return 0;
}

3. 浮点型(Floating-Point Types)

#include <iostream>
#include <iomanip>
#include <cfloat>
using namespace std;
 
int main() {
    // 浮点类型
    float f = 3.14159f;           // 单精度,通常4字节,6-7位有效数字
    double d = 3.141592653589793; // 双精度,通常8字节,15-16位有效数字
    long double ld = 3.141592653589793238L; // 扩展精度,通常8-16字节
    
    // 科学计数法
    float scientific = 1.23e-4f;  // 0.000123
    double bigNum = 1.5e308;      // 非常大的数
    
    // 特殊值
    float inf = 1.0f / 0.0f;      // 正无穷
    float negInf = -1.0f / 0.0f;  // 负无穷
    float nan = 0.0f / 0.0f;      // NaN (Not a Number)
    
    // 精度展示
    cout << fixed << setprecision(20);
    cout << "float: " << f << endl;
    cout << "double: " << d << endl;
    cout << "long double: " << ld << endl;
    
    // 范围展示
    cout << "float range: " << FLT_MIN << " to " << FLT_MAX << endl;
    cout << "double range: " << DBL_MIN << " to " << DBL_MAX << endl;
    
    return 0;
}

4. 布尔型(Boolean Type)

#include <iostream>
using namespace std;
 
int main() {
    bool flag1 = true;   // true = 1
    bool flag2 = false;  // false = 0
    bool flag3 = 100;    // 非零值转换为true
    bool flag4 = 0;      // 0转换为false
    
    cout << "bool size: " << sizeof(bool) << " byte" << endl;
    cout << "true value: " << true << endl;   // 输出1
    cout << "false value: " << false << endl; // 输出0
    cout << boolalpha;  // 设置输出为true/false
    cout << "true: " << true << ", false: " << false << endl;
    
    return 0;
}

5. 空类型(Void Type)

void function() {
    // void函数不返回值
}
 
void* genericPointer;  // void指针可以指向任何类型
int x = 10;
genericPointer = &x;   // 但需要类型转换才能使用
int* intPtr = static_cast<int*>(genericPointer);

二、类型修饰符和限定符

1. const 限定符

#include <iostream>
using namespace std;
 
int main() {
    const int MAX_SIZE = 100;        // 常量,不能修改
    const double PI = 3.14159;       
    
    // 指针和const
    int value = 42;
    const int* ptr1 = &value;        // 指向常量的指针(不能通过ptr1修改值)
    int* const ptr2 = &value;        // 常量指针(ptr2本身不能改变)
    const int* const ptr3 = &value;  // 指向常量的常量指针
    
    // const成员函数
    class MyClass {
        int data;
    public:
        int getData() const {         // const成员函数,不修改对象状态
            return data;
        }
    };
    
    return 0;
}

2. volatile 限定符

volatile int hardwareRegister;  // 告诉编译器该变量可能被外部改变
volatile bool flag;             // 常用于多线程或硬件编程

3. mutable 限定符

class CacheClass {
    mutable int cacheValue;     // 即使在const成员函数中也可修改
    mutable bool cacheValid;
public:
    int getValue() const {
        if (!cacheValid) {
            cacheValue = computeValue();  // 可以修改mutable成员
            cacheValid = true;
        }
        return cacheValue;
    }
private:
    int computeValue() const { return 42; }
};

三、派生数据类型

1. 数组(Arrays)

#include <iostream>
#include <array>
using namespace std;
 
int main() {
    // C风格数组
    int arr1[5] = {1, 2, 3, 4, 5};
    int arr2[] = {1, 2, 3};           // 自动推导大小
    int arr3[5] = {1, 2};             // 部分初始化,其余为0
    
    // 多维数组
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 动态数组
    int* dynArr = new int[10];
    delete[] dynArr;
    
    // std::array (C++11)
    array<int, 5> stdArr = {1, 2, 3, 4, 5};
    cout << "Size: " << stdArr.size() << endl;
    
    return 0;
}

2. 指针(Pointers)

#include <iostream>
#include <memory>
using namespace std;
 
int main() {
    // 基本指针
    int x = 42;
    int* ptr = &x;              // 指向int的指针
    int** pptr = &ptr;          // 指向指针的指针
    
    // 空指针
    int* nullPtr = nullptr;     // C++11推荐方式
    int* nullPtr2 = NULL;       // C风格
    int* nullPtr3 = 0;          // 另一种方式
    
    // 函数指针
    int (*funcPtr)(int, int);   // 指向函数的指针
    
    // 智能指针 (C++11)
    unique_ptr<int> uptr(new int(42));        // 唯一所有权
    shared_ptr<int> sptr = make_shared<int>(42); // 共享所有权
    weak_ptr<int> wptr = sptr;                // 弱引用
    
    return 0;
}

3. 引用(References)

#include <iostream>
using namespace std;
 
int main() {
    int x = 42;
    int& ref = x;               // 左值引用
    const int& cref = x;        // 常量引用
    
    // 右值引用 (C++11)
    int&& rref = 42;            // 可以绑定到临时对象
    int&& rref2 = move(x);      // 使用move转换为右值
    
    // 引用作为函数参数
    auto swap = [](int& a, int& b) {
        int temp = a;
        a = b;
        b = temp;
    };
    
    return 0;
}

四、用户自定义类型

1. 结构体(Structures)

#include <iostream>
using namespace std;
 
// 基本结构体
struct Point {
    double x;
    double y;
    
    // C++中结构体可以有成员函数
    double distance() {
        return sqrt(x*x + y*y);
    }
};
 
// 带构造函数的结构体
struct Rectangle {
    int width;
    int height;
    
    Rectangle(int w, int h) : width(w), height(h) {}
    
    int area() const {
        return width * height;
    }
};
 
int main() {
    Point p1 = {3.0, 4.0};
    Point p2{1.0, 2.0};        // C++11统一初始化
    
    Rectangle rect(10, 20);
    cout << "Area: " << rect.area() << endl;
    
    return 0;
}

2. 联合体(Unions)

#include <iostream>
using namespace std;
 
union Data {
    int i;
    float f;
    char str[20];
};
 
// C++11 带标签的联合体
struct TaggedUnion {
    enum Type { INT, FLOAT, STRING } type;
    union {
        int i;
        float f;
        char str[20];
    };
};
 
int main() {
    Data data;
    data.i = 10;
    cout << data.i << endl;
    
    data.f = 3.14;  // 覆盖之前的值
    cout << data.f << endl;
    
    return 0;
}

3. 枚举(Enumerations)

#include <iostream>
using namespace std;
 
// C风格枚举
enum Color {
    RED,      // 0
    GREEN,    // 1
    BLUE      // 2
};
 
// 指定值的枚举
enum Status {
    SUCCESS = 0,
    ERROR = -1,
    PENDING = 100
};
 
// 强类型枚举 (C++11)
enum class Direction : char {
    North = 'N',
    South = 'S',
    East = 'E',
    West = 'W'
};
 
int main() {
    Color c = RED;
    Status s = SUCCESS;
    Direction d = Direction::North;
    
    // 强类型枚举需要显式转换
    char dirChar = static_cast<char>(d);
    
    return 0;
}

4. 类(Classes)

#include <iostream>
using namespace std;
 
class Person {
private:
    string name;
    int age;
    
public:
    // 构造函数
    Person(const string& n, int a) : name(n), age(a) {}
    
    // 成员函数
    void display() const {
        cout << "Name: " << name << ", Age: " << age << endl;
    }
    
    // 析构函数
    ~Person() {
        cout << "Person destroyed" << endl;
    }
};

五、C++11及之后的新类型

1. auto 类型推导

#include <iostream>
#include <vector>
using namespace std;
 
int main() {
    auto i = 42;                        // int
    auto d = 3.14;                      // double
    auto s = "hello"s;                  // string (C++14)
    
    vector<int> vec = {1, 2, 3};
    auto it = vec.begin();              // vector<int>::iterator
    
    // 函数返回类型推导 (C++14)
    auto lambda = [](auto x, auto y) {
        return x + y;
    };
    
    return 0;
}

2. decltype 类型推导

int x = 5;
decltype(x) y = 10;           // y是int类型
decltype((x)) z = x;          // z是int&类型
 
// 结合auto使用
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

3. nullptr 类型

#include <iostream>
using namespace std;
 
void func(int) { cout << "int version" << endl; }
void func(void*) { cout << "pointer version" << endl; }
 
int main() {
    func(0);        // 调用int版本
    func(NULL);     // 可能有歧义
    func(nullptr);  // 明确调用pointer版本
    
    return 0;
}

六、STL容器类型

1. 序列容器

#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <array>
#include <forward_list>
using namespace std;
 
int main() {
    // 动态数组
    vector<int> vec = {1, 2, 3, 4, 5};
    
    // 双端队列
    deque<int> deq = {1, 2, 3};
    
    // 双向链表
    list<int> lst = {1, 2, 3};
    
    // 固定大小数组 (C++11)
    array<int, 5> arr = {1, 2, 3, 4, 5};
    
    // 单向链表 (C++11)
    forward_list<int> flst = {1, 2, 3};
    
    return 0;
}

2. 关联容器

#include <iostream>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
using namespace std;
 
int main() {
    // 有序集合
    set<int> s = {3, 1, 4, 1, 5};
    multiset<int> ms = {1, 1, 2, 2, 3};
    
    // 有序映射
    map<string, int> m = {{"one", 1}, {"two", 2}};
    multimap<string, int> mm;
    
    // 无序集合 (C++11)
    unordered_set<int> us = {1, 2, 3};
    unordered_multiset<int> ums;
    
    // 无序映射 (C++11)
    unordered_map<string, int> um = {{"a", 1}};
    unordered_multimap<string, int> umm;
    
    return 0;
}

七、特殊数据类型

1. std::optional (C++17)

#include <iostream>
#include <optional>
using namespace std;
 
optional<int> divide(int a, int b) {
    if (b == 0) return nullopt;
    return a / b;
}
 
int main() {
    auto result = divide(10, 2);
    if (result.has_value()) {
        cout << "Result: " << result.value() << endl;
    }
    
    // 或使用value_or提供默认值
    cout << divide(10, 0).value_or(-1) << endl;
    
    return 0;
}

2. std::variant (C++17)

#include <iostream>
#include <variant>
#include <string>
using namespace std;
 
int main() {
    variant<int, float, string> v;
    v = 42;
    cout << get<int>(v) << endl;
    
    v = 3.14f;
    cout << get<float>(v) << endl;
    
    v = "hello"s;
    cout << get<string>(v) << endl;
    
    // 访问器模式
    visit([](auto&& arg) {
        cout << arg << endl;
    }, v);
    
    return 0;
}

3. std::any (C++17)

#include <iostream>
#include <any>
using namespace std;
 
int main() {
    any a = 42;
    cout << any_cast<int>(a) << endl;
    
    a = 3.14;
    cout << any_cast<double>(a) << endl;
    
    a = "hello"s;
    cout << any_cast<string>(a) << endl;
    
    // 类型检查
    if (a.type() == typeid(string)) {
        cout << "a contains a string" << endl;
    }
    
    return 0;
}

4. std::tuple

#include <iostream>
#include <tuple>
using namespace std;
 
int main() {
    // 创建元组
    tuple<int, string, double> t(42, "hello", 3.14);
    
    // 访问元素
    cout << get<0>(t) << endl;  // 42
    cout << get<1>(t) << endl;  // hello
    cout << get<2>(t) << endl;  // 3.14
    
    // 结构化绑定 (C++17)
    auto [id, name, score] = t;
    cout << id << " " << name << " " << score << endl;
    
    // make_tuple
    auto t2 = make_tuple(1, 2.0, "three");
    
    return 0;
}

八、类型转换

1. 隐式类型转换

int i = 42;
double d = i;        // int到double的隐式转换
char c = 'A';
int ascii = c;       // char到int的隐式转换

2. 显式类型转换(C++风格)

#include <iostream>
using namespace std;
 
class Base { virtual void dummy() {} };
class Derived : public Base {};
 
int main() {
    // static_cast - 编译时转换
    double d = 3.14;
    int i = static_cast<int>(d);
    
    // dynamic_cast - 运行时类型检查(用于多态)
    Base* base = new Derived();
    Derived* derived = dynamic_cast<Derived*>(base);
    
    // const_cast - 移除const属性
    const int ci = 42;
    int* pi = const_cast<int*>(&ci);
    
    // reinterpret_cast - 重新解释位模式
    int* ip = new int(42);
    long addr = reinterpret_cast<long>(ip);
    
    return 0;
}

九、类型别名

// typedef传统方式
typedef unsigned long ulong;
typedef int (*FuncPtr)(int, int);
 
// using现代方式 (C++11)
using ulong = unsigned long;
using FuncPtr = int(*)(int, int);
 
// 模板别名 (C++11)
template<typename T>
using Vec = std::vector<T>;
 
Vec<int> numbers = {1, 2, 3, 4, 5};

十、类型特性(Type Traits)

#include <iostream>
#include <type_traits>
using namespace std;
 
template<typename T>
void checkType() {
    cout << "Is integral: " << is_integral<T>::value << endl;
    cout << "Is floating point: " << is_floating_point<T>::value << endl;
    cout << "Is pointer: " << is_pointer<T>::value << endl;
    cout << "Is class: " << is_class<T>::value << endl;
}
 
int main() {
    checkType<int>();
    checkType<double>();
    checkType<string>();
    
    // 条件类型选择
    using Type = conditional<true, int, double>::type;  // Type是int
    
    return 0;
}

总结

C++提供了丰富的数据类型系统,从基本类型到复杂的模板类型,每种类型都有其特定的用途:

  1. 基本类型:用于存储简单数据
  2. 派生类型:通过组合基本类型创建更复杂的数据结构
  3. 用户定义类型:允许创建符合特定需求的自定义类型
  4. STL容器:提供高效的数据管理方案
  5. 现代C++类型:提供更安全、更灵活的类型系统