You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++静态类实例机制解析:单例模式下为何实例状态不一致?

问题分析与解答

核心误区拆解

你遇到的问题源于三个关键误解:

1. 错误拷贝了单例实例

在init函数中,这段代码是问题核心:

Shape singleton = Shape::getInstance();

getInstance()返回的是单例对象的引用,但Shape singleton = ...的写法会触发C++的拷贝构造函数,创建一个全新的局部Shape对象。后续修改singleton.width只是修改这个局部拷贝的成员变量,和getInstance()里的静态单例对象毫无关系。你看到的第一个输出37,是这个局部拷贝对象的width值,而非单例的。

2. 单例模式的实现不完整

你的代码并没有实现真正的单例:

  • 类的构造函数默认是public的,外部可以直接创建新实例(比如main里的Shape rectangle;就是一个独立实例)
  • 没有禁用拷贝构造和赋值运算符,导致可以随意拷贝实例

真正的单例需要将构造函数、拷贝构造函数、赋值运算符都设为private,确保外部无法创建新实例或拷贝已有实例。

3. 多个独立实例的内存隔离

程序中存在三个完全独立的Shape实例:

  • getInstance()函数内的静态obj:你想实现的单例
  • init函数内的局部singleton:单例的拷贝对象
  • main函数内的rectangle:独立创建的实例

这三个实例的width成员变量存储在不同内存地址,修改其中一个不会影响另外两个。rectangle的width保持默认值0,所以第二个输出是0。

修正后的代码示例

如果要正确实现单例并修改其成员变量,代码应调整为:

#include <iostream>
#include <ctime>

using namespace std;

class Shape {
   public:
      static Shape& getInstance() {
         static Shape obj;
         return obj;
      }

      void init() {
          // 用引用接收单例,避免拷贝
          Shape& singleton = Shape::getInstance();
          srand((unsigned)time(0));
          singleton.width = rand()%100;
          singleton.printWidth();
      }

      void printWidth(){
        cout<<width<<endl;
      }
      
   private:
      // 构造函数设为private,禁止外部创建实例
      Shape() = default;
      // 禁用拷贝构造和赋值运算符
      Shape(const Shape&) = delete;
      Shape& operator=(const Shape&) = delete;

      int width = 0;
};

int main()
{
   // 无法直接创建实例,必须通过getInstance获取
   Shape& rectangle = Shape::getInstance();
   rectangle.init();
   rectangle.printWidth();
   
   return 0;
}

此时输出会是两个相同的随机数,因为操作的是同一个单例实例。

内容的提问来源于stack exchange,提问作者Star-lordX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:15:28