Static member variables in C++

Static keyword in C

In the lesson on file scope and the static keyword, you learned that static variables keep their values and are not destroyed even after they go out of scope. For example:

int GenerateID()
{
    static int s_nID = 0;
    return s_nID++;
}
 
int main()
{
    std::cout << GenerateID() << std::endl;
    std::cout << GenerateID() << std::endl;
    std::cout << GenerateID() << std::endl;
    return 0;
}

This program prints:

0
1
2

Note that s_nID has kept it’s value across multiple function calls.

The static keyword has another meaning when applied to global variables — it changes them from global scope to file scope. Because global variables are typically avoided by competent programmers, and file scope variables are just global variables limited to a single file, the static keyword is typically not used in this capacity.

Static member variables

C++ introduces two new uses for the static keyword when applied to classes: static member variables, and static member classes. Before we go into the static keyword as applied to member variables, first consider the following class:

class Something
{
private:
    int m_nValue;
public:
    Something() { m_nValue = 0; }
};
 
int main()
{
    Something cFirst;
    Something cSecond;
    return 0;
}
When we instantiate a class object, each object gets it’s own copy of all normal member variables. In this case, because we have declared two Something class objects, we end up with two copies of m_nValue — one inside cFirst, and one inside cSecond. cFirst->m_nValue is different than cSecond->m_nValue.

Member variables of a class can be made static by using the static keyword. Static member variables only exist once in a program regardless of how many class objects are defined! One way to think about it is that all objects of a class share the static variables. Consider the following program:

class Something
{
public:
    static int s_nValue;
};
 
int Something::s_nValue = 1;
 
int main()
{
    Something cFirst;
    cFirst.s_nValue = 2;
 
    Something cSecond;
    std::cout << cSecond.s_nValue;
 
    return 0;
}
This program produces the following output:

2

Because s_nValue is a static member variable, s_nValue is shared between all objects of the class. Consequently, cFirst.s_nValue is the same as cSecond.s_nValue. The above program shows that the value we set using cFirst can be accessed using cSecond!

Although you can access static members through objects of the class type, this is somewhat misleading. cFirst.s_nValue implies that s_nValue belongs to cFirst, and this is really not the case. s_nValue does not belong to any object. In fact, s_nValue exists even if there are no objects of the class have been instantiated!

Consequently, it is better to think of static members as belonging to the class itself, not the objects of the class. Because s_nValue exists independently of any class objects, it can be accessed directly using the class name and the scope operator:

class Something
{
public:
    static int s_nValue;
};
 
int Something::s_nValue = 1;
 
int main()
{
    Something::s_nValue = 2;
    std::cout << Something::s_nValue;
    return 0;
}

In the above snippet, s_nValue is referenced by class name rather than through an object. Note that we have not even instantiated an object of type Something, but we are still able to access and use Something::s_nValue. This is the preferred method for accessing static members.

Initializing static member variables

Because static member variables are not part of the individual objects, you must explicitly define the static member if you want to initialize it to a non-zero value. The following line in the above example initializes the static member to 1:

int Something::s_nValue = 1;
This initializer should be placed in the code file for the class (eg. Something.cpp). In the absense of an initializing line, C++ will initialize the value to 0.

An example of static member variables

Why use static variables inside classes? One great example is to assign a unique ID to every instance of the class. Here’s an example of that:

class Something
{
private:
    static int s_nIDGenerator;
    int m_nID;
public:
    Something() { m_nID = s_nIDGenerator++; }
 
    int GetID() const { return m_nID; }
};
 
int Something::s_nIDGenerator = 1;
 
int main()
{
    Something cFirst;
    Something cSecond;
    Something cThird;
 
    using namespace std;
    cout << cFirst.GetID() << endl;
    cout << cSecond.GetID() << endl;
    cout << cThird.GetID() << endl;
    return 0;
}
This program prints:

1
2
3

Because s_nIDGenerator is shared by all Something objects, when a new Something object is created, it’s constructor grabs the current value out of s_nIDGenerator and then increments the value for the next object. This guarantees that each Something object receives a unique id (incremented in the order of creation). This can really help when debugging multiple items in an array, as it provides a way to tell multiple objects of the same class type apart!

Static member variables can also be useful when the class needs to utilize an internal lookup table (eg. to look up the name of something, or to find a pre-calculated value). By making the lookup table static, only one copy exists for all objects, rather than a copy for each object instantiated. This can save substantial amounts of memory.


http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

C++中,`static`关键字有多个作用,主要用于存储类别(storage class)和作用域控制。以下是静态关键字的主要用途: 1. 静态存储类别(Storage Class): - **Static Local Variables**: 在函数内部使用`static`声明的变量,其生命周期从定义开始直到程序结束,且仅有一个副本,即使函数被多次调用。这意味着它们只在首次调用时初始化,后续调用时保持不变。 - **Static Member Variables**(Class Variables):类中的静态成员变量在整个类实例化期间共享,无论创建了多少个对象,每个对象都有自己的静态成员函数的引用。 - **Static Member Functions**: 类中的静态成员函数不依赖于类的任何实例,可以直接通过类名调用。 2. 静态局部作用域: - 当静态变量出现在函数或代码块的开始时,它只在当前作用域可见,每次进入该作用域都会初始化一次。 3. 文件全局(File Scope): - 在头文件(`.h`)中声明的静态变量或函数,会在整个程序中全局可见,但仅在一个编译单元(translation unit)内初始化一次。 4. 内联函数: - `inline`关键字配合`static`可以提高内联函数的性能,因为编译器可能会在所有调用的地方直接替换内联代码,而不仅仅是`inline`声明的一次。 5. 链表节点的静态属性: - 在某些数据结构如静态链表中,静态成员可用于表示链表的头部或尾部元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值