MST

星途 面试题库

面试题:C++函数返回常量引用与对象生命周期管理

假设你有一个类`MyClass`,其中有一个函数`getInstance`返回`const MyClass&`。当该函数在一个复杂的多线程环境下使用时,可能会出现哪些关于对象生命周期管理的问题?如何解决这些问题?
36.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

可能出现的对象生命周期管理问题

  1. 对象提前析构:如果MyClass对象是在局部作用域创建,当局部作用域结束,对象会被析构。然而多线程环境下,其他线程可能还在使用通过getInstance获取的引用,这就导致了悬空引用,引发未定义行为。
  2. 资源竞争:如果MyClass对象的创建涉及到资源分配(如内存、文件句柄等),多个线程同时调用getInstance可能会导致资源竞争,出现重复分配或者分配失败等问题。

解决方法

  1. 使用单例模式
    • 饿汉式单例:在程序启动时就创建MyClass的实例,这样在多线程调用getInstance时,实例已经存在,避免了竞争。
class MyClass {
public:
    static const MyClass& getInstance() {
        static MyClass instance;
        return instance;
    }
private:
    MyClass() = default;
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
    ~MyClass() = default;
};
- **懒汉式单例(线程安全)**:在第一次调用`getInstance`时创建实例,并且使用互斥锁来保证线程安全。
#include <mutex>

class MyClass {
public:
    static const MyClass& getInstance() {
        static std::mutex mtx;
        static MyClass* instance = nullptr;
        std::lock_guard<std::mutex> lock(mtx);
        if (instance == nullptr) {
            instance = new MyClass();
        }
        return *instance;
    }
private:
    MyClass() = default;
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
    ~MyClass() = default;
};
  1. 智能指针:如果不能使用单例模式,可以使用智能指针来管理MyClass对象的生命周期。例如std::shared_ptr,它会在引用计数为0时自动释放对象。
#include <memory>

class MyClass;
std::shared_ptr<MyClass> globalInstance;

class MyClass {
public:
    static const MyClass& getInstance() {
        static std::mutex mtx;
        std::lock_guard<std::mutex> lock(mtx);
        if (!globalInstance) {
            globalInstance = std::make_shared<MyClass>();
        }
        return *globalInstance;
    }
private:
    MyClass() = default;
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
    ~MyClass() = default;
};