【C++】静态成员 static

本文探讨了C++中的静态成员,包括它们的存储位置、访问方式及与全局变量的区别。重点讲解了静态成员在单例模式中的应用,如何确保类只有一个实例,并提供了避免new/delete误区的相关说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态成员 static

静态成员:被static修饰的成员变量/函数,只占一份内存

  • 存储在数据段(全局区,类似于全局变量)

在这里插入图片描述

  • 可以通过

    • 对象访问(对象.静态成员)
      在这里插入图片描述

    • 对象指针访问(对象指针->静态成员)
      在这里插入图片描述

    • 类访问(类名::静态成员)

      Car::m_price = 400
      
  • 必须初始化,必须放在类外面初始化再使用,在外面不能再写static了
    在这里插入图片描述
    不能使用int m_price = 0;,这样只是初始化了一个同名的变量。

  • 就算在main里没有创建Car对象,直接打印Car::m_price也可以,不依赖类存在,因为是全局变量

  • 对比全局变量,它可以设定访问权限(public、protected、private),达到局部共享的目的
    在这里插入图片描述

  • 如果类的声明和实现分离,比如类的声明在.h文件,具体实现在.cpp文件,需要在.cpp中初始化。

静态成员函数

被static修饰的成员函数
在这里插入图片描述
只要是静态成员,都有三种访问方式(对象、指针、类)

  • 内部不能使用this指针

    也不能访问内部成员变量(相当于使用this)

    this指针只能用在非静态成员函数内部

  • 静态成员函数不能是虚函数

    虚函数只能是非静态成员函数

  • 静态成员内部不能访问非静态成员变量\函数,只能访问静态成员变量\函数

  • 非静态成员函数内部可以访问静态函数变量\函数

  • 构造函数、析构函数不能是静态

    因为构造函数和析构函数是针对对象的,静态成员并不在对象内

  • 当声明和实现分离时,实现部分不能带static

static应用
单例模式

设计模式的一种,保证某个类永远只创建一个对象

  1. 构造函数\析构函数私有化
  2. 定义一个私有的static成员变量指向唯一的那个单例对象
  3. 提供一个公共的访问单例对象的接口
class Rocket {
private:    
    Rocket() {}    
    ~Rocket() {}    
    static Rocket *ms_rocket;
public:    
    static Rocket *sharedRocket() {        
        // 这里要考虑多线程安全        
        if (ms_rocket == NULL) {            
            ms_rocket = new Rocket();        
        }        
        return ms_rocket;    
    }    
    static void deleteRocket() {        
        if (ms_rocket != NULL) {            
            delete ms_rocket;        
        }    
    }
}
Rocket *Rocket::ms_rocket = NULL;
int main() {    
    Rocket *p = Rocket::sharedRocket();
}

无论调用多少次shareRocket,返回的地址都是一样的。

  • 完善

    int main() {    
        Rocket *p1 = Rocket::sharedRocket();
        Rocket *p2 = Rocket::sharedRocket();
        
        return 0;
    }
    // p1和p2的地址是一样的
    
    • 不允许有赋值操作,比如p1 = p2,这样是没有意义的,应该被禁止。

      所以就使用运算符重载来禁止。

      直接将赋值运算符私有化,这样赋值就会被禁止。

    • 其次拷贝构造函数也应该被私有化

    class Rocket {
    private:    
        Rocket() {}    
        ~Rocket() {}    
        static Rocket *ms_rocket;
        void operator=(const Rocket& rocket) {}
    public:    
        static Rocket *sharedRocket() {        
            // 这里要考虑多线程安全        
            if (ms_rocket == NULL) {            
                ms_rocket = new Rocket();        
            }        
            return ms_rocket;    
        }    
        static void deleteRocket() {        
            if (ms_rocket != NULL) {            
                delete ms_rocket;        
            }    
        }
    }
    
new\delete误区
int *p = new int; // 从堆空间分配四个字节给p
*p = 10;
delete p; 
// 回收堆空间

并不是说把p的四个字节清空

回收堆空间内存:这块堆空间内存可以重新被别人使用。然后再new int,可能被分配到的字节是之前被用过的字节

如果销毁同时清零会浪费效率。

所以如果需要清零就手动清零

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值