# c++中联合体和结构体的区别
面试时没有回答好问题是很正常的,被面试官质疑时,要有今天不会明天会的底气,面后做好复盘,不在同一道题目上跌倒第二次,今天就从 c++中联合体和结构体的区别 背起来
# 简要回答
在C++中,结构体(struct)和联合体(union)都是*用户定义的类型,但结构体所有成员同时存在且占用独立内存空间
而联合体所有成员共享同一内存空间,仅能存储一个成员的值。
C++11后,联合体可以包含非POD类型成员,并支持成员函数和特殊成员函数。
# 详细回答
- C++中的结构体特性:
默认所有成员和继承都是public的类
支持成员函数、构造函数、析构函数还支持继承和多态
内存布局与C结构体类似,但可能更复杂(因虚函数表等)
C++11后支持成员初始化列表
- C++中的联合体特性:
所有成员共享同一内存空间,C++11前只能包含POD类型成员,C++11后支持非POD类型,但需要显式管理生命周期
可以包含成员函数,包括构造函数和析构函数
不能继承也不能作为基类
不能包含虚函数或引用成员
- 关键差异:
在访问控制方面:结构体默认使用public(可以修改为别的),而联合体成员总是public
结构体支持多态,而联合体不支持多态
生命周期管理:联合体需要显式管理非POD成员
结构体可以使用于模板,但是联合体受限很多
# 代码示例
#include <iostream>
#include <string>
// C++结构体示例(带成员函数)
struct Student {
std::string name;
int age;
double score;
// 成员函数
void introduce() {
std::cout << "我叫" << name << ",今年" << age << "岁,成绩" << score << std::endl;
}
// 构造函数
Student(const std::string& n, int a, double s)
: name(n), age(a), score(s) {}
};
// C++11联合体示例(含非POD类型)
union Variant {
int i;
double d;
std::string s; // 非POD类型
// 构造函数
Variant() : i(0) {}
~Variant() {} // 需要自行管理字符串的生命周期
// 成员函数
void setInt(int val) { i = val; }
void setString(const std::string& str) {
new(&s) std::string(str); // placement new
}
void destroyString() {
s.~basic_string(); // 显式调用析构函数
}
};
int main() {
// 结构体使用
Student stu("张三", 20, 90.5);
stu.introduce();
// 联合体使用
Variant v;
v.setInt(42);
std::cout << "整数值: " << v.i << std::endl;
v.setString("Hello");
std::cout << "字符串值: " << v.s << std::endl;
v.destroyString();
// 查看大小
std::cout << "结构体大小: " << sizeof(Student) << " 字节" << std::endl;
std::cout << "联合体大小: " << sizeof(Variant) << " 字节" << std::endl;
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 知识拓展
- 知识图解

适用场景
1.C++结构体推荐场景
数据传输对象(DTO):在系统间传递数据
策略模式:作为策略的轻量级实现
模板元编程:作为编译期计算工具
接口简化:作为多个返回值的容器
内存布局控制:与硬件或网络协议交互
2.C++联合体推荐场景
变体类型:替代继承的轻量级方案
内存优化:嵌入式或高性能场景
二进制协议解析:解释网络数据包
类型转换:不同表示间的安全转换
- 面试官很能追问
Q1: C++中结构体和类有什么区别?
A: 在C++中,结构体和类几乎相同,主要区别在于: 默认访问权限:结构体成员默认public,类默认private 默认继承权限:结构体继承默认public,类默认private 惯例:结构体通常用于数据聚合,类用于更复杂的抽象
Q2: 为什么C++11允许联合体包含非POD类型?
A: 为了增加灵活性,但需要开发者手动管理生命周期。因为联合体不知道当前活跃成员是谁,无法自动调用正确的构造函数/析构函数,所以需要: 使用placement new初始化非POD成员 显式调用析构函数 确保在销毁联合体前正确清理
Q3: 如何安全地使用包含std::string的联合体?
A: 需要: 提供构造函数正确初始化活跃成员 在析构函数中检查并正确销毁非POD成员 实现拷贝/移动操作时正确处理活跃成员 使用标记字段跟踪当前活跃成员 或者使用C++17的std::variant替代
评论
验证登录状态...