• C++
  • C++ 结构体初始化学习笔记

  • @ 2025-8-10 14:41:56

C++ 结构体初始化学习笔记

结构体(Struct)是C++中一种重要的数据类型,用于将不同类型的数据组合在一起。结构体的初始化是使用结构体时的基础操作,本笔记将详细介绍C++中结构体初始化的各种方法。

1. 结构体的定义

首先,我们需要定义一个结构体才能进行初始化操作:

// 定义一个表示学生的结构体
struct Student {
    std::string name;  // 姓名
    int age;           // 年龄
    float score;       // 分数
    bool isMale;       // 是否为男性
};

2. 结构体初始化的基本方法

2.1 默认初始化

声明结构体变量时不提供初始值,成员变量会被默认初始化:

Student s1;  // 默认初始化,成员变量的值是不确定的(基本类型)或默认构造(类类型如string)

注意:基本类型(int, float等)的默认初始化值是不确定的,而类类型(如string)会调用其默认构造函数。

2.2 聚合初始化(Aggregate Initialization)

C++11之前的传统初始化方式,使用大括号{}进行初始化:

// C++11之前的聚合初始化
Student s2 = {"Alice", 18, 95.5f, false};

在C++11及以后,可以省略等号:

// C++11及以后的聚合初始化
Student s3{"Bob", 19, 88.0f, true};

注意:聚合初始化要求初始化值的顺序与结构体成员声明的顺序一致。

2.3 指定成员初始化(Designated Initializers)

C++20引入的新特性,可以通过成员名来初始化,不要求顺序:

// C++20指定成员初始化
Student s4{
    .age = 20,
    .name = "Charlie",
    .score = 92.3f,
    .isMale = true
};

这种方式的优点是清晰明了,尤其适合成员较多的结构体。

2.4 使用构造函数初始化

结构体可以像类一样拥有构造函数,从而提供更灵活的初始化方式:

struct Student {
    std::string name;
    int age;
    float score;
    bool isMale;
    
    // 构造函数
    Student(std::string n, int a, float s, bool m) 
        : name(n), age(a), score(s), isMale(m) {}
        
    // 带默认参数的构造函数
    Student(std::string n = "Unknown", int a = 0)
        : name(n), age(a), score(0.0f), isMale(false) {}
};

// 使用构造函数初始化
Student s5("David", 21, 78.5f, true);
Student s6("Eve");  // 使用带默认参数的构造函数
Student s7;         // 使用默认参数构造

3. 结构体数组的初始化

结构体数组可以使用类似的方式进行初始化:

// 结构体数组初始化
Student class1[3] = {
    {"Alice", 18, 95.5f, false},
    {"Bob", 19, 88.0f, true},
    {"Charlie", 20, 92.3f, true}
};

// C++11及以后可以省略等号
Student class2[3]{
    {"David", 21, 78.5f, true},
    {"Eve", 18, 91.0f, false},
    {"Frank", 19, 85.5f, true}
};

4. 动态分配的结构体初始化

使用new关键字动态分配结构体时的初始化方法:

// 动态分配结构体并初始化
Student* s8 = new Student{"Grace", 20, 89.5f, false};

// 动态分配结构体数组并初始化
Student* class3 = new Student[2]{
    {"Heidi", 19, 94.0f, false},
    {"Ivan", 20, 87.5f, true}
};

// 使用完后需要释放内存
delete s8;
delete[] class3;

5. 结构体嵌套初始化

当结构体中包含其他结构体时,可以进行嵌套初始化:

// 定义日期结构体
struct Date {
    int year;
    int month;
    int day;
};

// 包含结构体成员的结构体
struct Employee {
    std::string name;
    Date hireDate;
    float salary;
};

// 嵌套初始化
Employee emp1{
    "Jack",
    {2020, 3, 15},  // 嵌套初始化Date结构体
    5000.0f
};

// C++20指定成员的嵌套初始化
Employee emp2{
    .name = "Kate",
    .hireDate = {.year = 2019, .month = 7, .day = 22},
    .salary = 6000.0f
};

6. 示例代码

下面是一个综合示例,展示了各种结构体初始化方法:

#include <iostream>
#include <string>

// 基础结构体定义
struct Student {
    std::string name;
    int age;
    float score;
    bool isMale;
    
    // 构造函数
    Student(std::string n, int a, float s, bool m) 
        : name(n), age(a), score(s), isMale(m) {}
        
    // 带默认参数的构造函数
    Student(std::string n = "Unknown", int a = 0)
        : name(n), age(a), score(0.0f), isMale(false) {}
};

// 用于嵌套的结构体
struct Date {
    int year;
    int month;
    int day;
};

// 包含嵌套结构体的结构体
struct Employee {
    std::string name;
    Date hireDate;
    float salary;
};

void printStudent(const Student& s) {
    std::cout << "Name: " << s.name 
              << ", Age: " << s.age 
              << ", Score: " << s.score 
              << ", Male: " << (s.isMale ? "Yes" : "No") << std::endl;
}

void printEmployee(const Employee& e) {
    std::cout << "Name: " << e.name 
              << ", Hire Date: " << e.hireDate.year << "-" 
              << e.hireDate.month << "-" << e.hireDate.day 
              << ", Salary: " << e.salary << std::endl;
}

int main() {
    // 1. 默认初始化
    Student s1;
    std::cout << "1. Default initialization:" << std::endl;
    printStudent(s1);  // 注意:基本类型成员值不确定
    
    // 2. 聚合初始化
    Student s2 = {"Alice", 18, 95.5f, false};
    Student s3{"Bob", 19, 88.0f, true};
    std::cout << "\n2. Aggregate initialization:" << std::endl;
    printStudent(s2);
    printStudent(s3);
    
    // 3. 指定成员初始化 (C++20)
    Student s4{
        .age = 20,
        .name = "Charlie",
        .score = 92.3f,
        .isMale = true
    };
    std::cout << "\n3. Designated initializers (C++20):" << std::endl;
    printStudent(s4);
    
    // 4. 使用构造函数初始化
    Student s5("David", 21, 78.5f, true);
    Student s6("Eve");  // 使用带默认参数的构造函数
    Student s7;         // 使用默认参数构造
    std::cout << "\n4. Constructor initialization:" << std::endl;
    printStudent(s5);
    printStudent(s6);
    printStudent(s7);
    
    // 5. 结构体数组初始化
    Student class1[3] = {
        {"Frank", 18, 90.0f, true},
        {"Grace", 19, 85.5f, false},
        {"Heidi", 20, 93.0f, false}
    };
    std::cout << "\n5. Array of structs initialization:" << std::endl;
    for (const auto& s : class1) {
        printStudent(s);
    }
    
    // 6. 动态分配的结构体初始化
    Student* s8 = new Student{"Ivan", 20, 89.5f, true};
    std::cout << "\n6. Dynamically allocated struct:" << std::endl;
    printStudent(*s8);
    delete s8;
    
    // 7. 嵌套结构体初始化
    Employee emp1{
        "Jack",
        {2020, 3, 15},  // 嵌套初始化Date结构体
        5000.0f
    };
    
    // C++20指定成员的嵌套初始化
    Employee emp2{
        .name = "Kate",
        .hireDate = {.year = 2019, .month = 7, .day = 22},
        .salary = 6000.0f
    };
    std::cout << "\n7. Nested struct initialization:" << std::endl;
    printEmployee(emp1);
    printEmployee(emp2);
    
    return 0;
}

7. 注意事项

  1. 聚合类型要求:使用聚合初始化时,结构体不能有用户定义的构造函数、基类或虚函数。

  2. 初始化顺序

    • 聚合初始化必须按成员声明顺序提供值
    • 指定成员初始化(C++20)可以不按顺序
  3. 兼容性

    • 指定成员初始化是C++20的特性,需要编译器支持
    • 不同编译器对C++标准的支持程度可能不同
  4. 部分初始化

    • 对结构体进行部分初始化时,未指定的成员会被值初始化(基本类型为0,指针为nullptr等)
// 部分初始化示例
Student s_partial{"Jane"};  // 只初始化name,其他成员使用默认值
Student s_partial2{.name = "John", .score = 85.0f};  // C++20

通过本笔记的学习,你应该掌握了C++结构体初始化的各种方法,能够根据实际需求选择合适的初始化方式。在实际编程中,建议使用最清晰、不易出错的方式进行结构体初始化。

0 条评论

目前还没有评论...