快速了解static

static用来控制变量的存储方式和可见性。

[[toc]]

静态变量

函数中的静态变量

static_vaiable.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>


void demo() {
// static variable
static int count = 0;
std::cout << count << " ";

count++;
}

int main() {
for(int i = 0; i < 5; i++) {
demo();
}
return 0;
}

执行输出:

1
2
3
g++ -o test.o static_vaiable.cpp

./test.o

输出:

0 1 2 3 4

当变量声明为static时,空间将在程序的生命周期内分配。即使多次调用该函数,静态变量的空间也只分配一次。

在多个函数中使用static

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//main.cpp

#include <iostream>

int s_Variable = 10;

int main() {
std::cout << s_Variable << std::endl;
return 0;
}

// static.cpp

static int s_Variable = 5;

编译执行:

1
2
g++ -o test.o main.cpp static.cpp
./test.o

输出:

10

现在我们把static.cpp中的static去掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//main.cpp

#include <iostream>

int s_Variable = 10;

int main() {
std::cout << s_Variable << std::endl;
return 0;
}

// static.cpp

int s_Variable = 5;

编译:

1
g++ -o test.o main.cpp static.cpp

此时会出现链接错误:

1
2
3
4
5
duplicate symbol '_s_Variable' in:
/var/folders/wb/pjgtxmjd1pd76j9qs__63hh40000gp/T/main-71027a.o
/var/folders/wb/pjgtxmjd1pd76j9qs__63hh40000gp/T/static-7f2470.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

因为s_Variable已经在另一个编译单元里面定义了,所以两个全局变量的名字不能一样。

一种解决方法为使用extern关键字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//main.cpp

#include <iostream>

extern int s_Variable;

int main() {
std::cout << s_Variable << std::endl;
return 0;
}

// static.cpp

int s_Variable = 5;

输出:

5

static只在当前的文件(.cpp)下可见。

类中的静态变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//nostatic_class.cpp

#include <iostream>

class Entity {
public:
int x, y;

void Print() {
std::cout << x << " " << y << std::endl;
}
};

int main() {
Entity e;
e.x = 1;
e.y = 2;

Entity e1 = {5, 8};

e.Print();
e1.Print();
return 0;
}

输出:

1 2
5 8

现在我们把x,y改为static

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// static_class.cpp

#include <iostream>

class Entity {
public:
static int x, y;

void Print() {
std::cout << x << " " << y << std::endl;
}
};

int main() {
Entity e;
e.x = 1;
e.y = 2;

Entity e1;
e1.x = 5;
e1.y = 8;

e.Print();
e1.Print();
return 0;
}

编译:

1
g++ -o test.o static_class.cpp

输出:

1
2
3
4
5
6
7
8
9
Undefined symbols for architecture x86_64:
"Entity::x", referenced from:
_main in static_class-65b492.o
Entity::Print() in static_class-65b492.o
"Entity::y", referenced from:
_main in static_class-65b492.o
Entity::Print() in static_class-65b492.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这是因为静态变量是由所有对象共享的,不能在类中进行定义,在类中只是声明,必须在类外定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// static_class.cpp

#include <iostream>

class Entity {
public:
static int x, y;

void Print() {
std::cout << x << " " << y << std::endl;
}
};

int Entity::x;
int Entity::y;

int main() {
Entity e;
e.x = 1;
e.y = 2;

Entity e1;
e1.x = 5;
e1.y = 8;

e.Print();
e1.Print();
return 0;
}

编译执行:

1
2
g++ -o test.o static_class.cpp
./test.o

输出:

5 8
5 8

你可能会好奇为什么最后结果会是两个5,8,这是因为static修饰的类使用的是一块内存,e1改动了,e中的元素也会发生改动。

静态成员

类中的静态函数

静态成员函数仅允许访问静态成员或其他静态成员函数,它们无法访问类的非静态数据成员或成员函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// static_function.cpp

#include <iostream>

class Entity {
public:
int x, y;

static void Print() {
std::cout << x << " " << y << std::endl; // invalid use of member 'x' and 'y' in static member function
}
};



int main() {
Entity e;
e.x = 1;
e.y = 2;

Entity e1;
e1.x = 5;
e1.y = 8;

e.Print();
e1.Print();
return 0;
}

当然可以通过实例来访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

class Entity {
public:
int x, y;

static void Print();
};

static void Print(Entity e) {
std::cout << e.x << " " << e.y << std::endl;
}

int main() {
Entity e;
e.x = 1;
e.y = 2;

Entity e1;
e1.x = 5;
e1.y = 8;

Print(e);
Print(e1);
return 0;
}

输出:

1 2
5 8