从零开始的C++那些事儿(一)
项目介绍
这是笔者自己阅读C++那些事的过程中的笔记整理。该项目是一个适合初学者从入门到进阶的C++仓库。这里笔者和大家分享自己的阅读过程。希望大家在C++的学习过程中能够找到自己的乐趣。
static那些事
static关键字与不同的类型使用时,具有不太的含义。
静态变量
- 函数中的变量:当变量声明为static时,空间将在程序的生命周期内分配。即使多次调用该函数,静态变量的空间也只分配一次,前一次调用中的变量值通过下一次函数调用传递。可用于需要存储先前函数状态的场景。
#include <iostream>
#include <string>
using namespace std;
void func()
{
// static variable
static int count = 0;
cout << count << " ";
// value is updated and
// will be carried to next
// function calls
count++;
}
int main()
{
for (int i = 0; i < 5; i++)
func();
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
输出:
0 1 2 3 4
- 1
上面程序中的变量count被声明为static。因此,它的值通过函数调用来传递。每次调用函数时,都不会对变量计数进行初始化。
- 类中的静态变量
类中的静态变量由对象共享。对于不同的对象,都拥有相同的静态变量。因此,静态变量不能通过构造函数初始化。一般来说,可以在类的源文件中对静态函数进行初始化。
//Object.h
class Object
{
public:
static int i;
Object();
};
//Object.cpp
#include "Object.h"
int Object::i = 10;
Object::Object()
{
}
//main.cpp
#include <iostream>
#include "Object.h"
using namespace std;
int main()
{
Object a;
Object b;
cout << a.i << " " << b.i << endl;
a.i = 1;
cout << a.i << " " << b.i << endl;
b.i = 2;
cout << a.i << " " << b.i << endl;
Object::i = 3;
cout << a.i << " " << b.i << endl;
}
- 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
- 31
- 32
- 33
- 34
- 35
输出:
10 10
1 1
2 2
3 3
- 1
- 2
- 3
- 4
上述代码中,Object类中拥有静态变量i,那么对象a和对象b都共享该变量。当该静态变量的值被更改后,对象a和对象b都会获取到被更改之后的新值。
静态成员
静态的类对象和静态变量一样,在声明为static时,空间将在程序的生命周期内分配。
普通类对象的生命周期:
#include <iostream>
using namespace std;
class Object
{
public:
Object()
{
cout << "Inside Constructor
";
}
~Object()
{
cout << "Inside Destructor
";
}
};
int main()
{
{
Object a;
}
cout << "End of main
";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
输出:
Inside Constructor
Inside Destructor
End of main
- 1
- 2
- 3
静态类对象的声明周期:
#include <iostream>
using namespace std;
class Object
{
public:
Object()
{
cout << "Inside Constructor
";
}
~Object()
{
cout << "Inside Destructor
";
}
};
int main()
{
{
static Object a;
}
cout << "End of main
";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
输出:
Inside Constructor
End of main
Inside Destructor
- 1
- 2
- 3
通过上面两段代码不难看出,普通的类对象在程序运行到作用范围之外时调用析构函数;静态类对象在程序生命周期结束时,才调用析构函数。
类中的静态函数
类中的静态函数不依赖于类的对象。我们可以使用对象和’.‘来调用静态静态成员函数,但是更推荐使用类名和范围解析运算符’::‘调用静态成员。
class Object
{
public:
static void print()
{
cout << "Hello, Static!
";
}
};
int main()
{
Object::print();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出:
Hello, Static!
- 1
单例模式
static变量在C++中是线程安全的。利用该特性可以通过简单的几行代码,在C++中实现一个线程安全的单例类。
#include <iostream>
using namespace std;
template<typename T>
class Singleton
{
private:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
protected:
Singleton() { }
public:
static T& Instance()
{
static T instance;
return instance;
}
virtual ~Singleton() { }
};
class Object : public Singleton<Object>
{
public:
void print()
{
cout << "Hello, Singleton!
";
}
};
//main function
int main()
{
Object::Instance().print();
}
- 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
- 31
- 32
- 33
- 34
输出:
Hello, Singleton!
- 1
推荐阅读