面试题答案
一键面试const声明
- 生命周期管理:
- 被
const
声明的数据在其作用域内保持常量性。其生命周期与普通变量相同,取决于定义的位置。例如在函数内定义的const
复杂结构体变量,在函数结束时生命周期结束;在全局定义的const
复杂结构体变量,生命周期贯穿整个程序运行。 - 由于是常量,内存一旦分配,其内容不可改变,这有助于确保数据在特定作用域内的稳定性。
- 被
- 可变性特点:
const
声明的数据不可变。对于包含引用类型字段的自定义结构体,引用本身不可变,即不能再引用其他对象,但引用所指向的对象内容是否可变取决于对象本身的定义。例如,如果引用指向的是一个非const
对象,理论上可以通过该引用修改对象内容,但由于整个结构体是const
,这种修改通常会被编译器阻止。
static声明
- 生命周期管理:
static
声明的数据具有静态存储期。在函数内定义的static
复杂结构体变量,其生命周期从程序开始到结束,而不是函数调用结束。全局的static
变量与普通全局变量类似,但其作用域被限制在声明所在的文件内。- 内存只分配一次,在程序启动时初始化,在程序结束时销毁。
- 可变性特点:
static
变量本身是可变的(除非同时用const
修饰)。对于复杂结构体中的引用类型字段,只要结构体本身不是const
,引用可以重新指向其他对象,并且引用所指向对象的内容也可以修改(如果对象允许修改)。
多线程环境下的问题及解决方法
- 问题:
- 数据竞争:如果多个线程同时访问和修改
static
或非const
的复杂结构体数据,可能会导致数据竞争。例如,一个线程正在修改结构体中某个引用所指向对象的内容,同时另一个线程也在读取或修改同一内容,会导致未定义行为。 - 初始化问题:对于
static
变量,多个线程可能同时尝试初始化它,这可能导致重复初始化或其他不一致问题。
- 数据竞争:如果多个线程同时访问和修改
- 解决方法:
- 互斥锁(Mutex):使用互斥锁来保护对共享数据(
static
或非const
数据)的访问。在访问数据前锁定互斥锁,访问结束后解锁。例如在C++中可以使用std::mutex
,在Java中可以使用synchronized
关键字。 - 读写锁(Read - Write Lock):如果读操作频繁而写操作较少,可以使用读写锁。多个线程可以同时进行读操作,但写操作时需要独占锁。如C++的
std::shared_mutex
。 - 线程局部存储(Thread - Local Storage,TLS):对于
static
变量,如果每个线程需要有自己独立的副本,可以使用线程局部存储。在C++中可以使用thread_local
关键字来声明线程局部变量。这样每个线程都有自己独立的变量副本,避免了多线程间的数据竞争。
- 互斥锁(Mutex):使用互斥锁来保护对共享数据(