static 是 C++ 中常用的關鍵字,被 static 修飾的變量只會在 靜態(tài)存儲區(qū)(常量數據也存放在這里) 被分配一次內存,生命周期與整個程序一樣,隨著程序的消亡而消亡。
一? static 有以下幾種用法:
1. 在文件中定義的 靜態(tài)全局變量
2. 在函數中定義的靜態(tài)變量
3. 類的靜態(tài)成員變量
4. 靜態(tài)類對象
5. 類的靜態(tài)方法
1. 在文件中定義的 靜態(tài)全局變量
// main.cpp
#include<iostream>
int xxx = 66;
static int yyy = 888;
int main()
{
std::cout << xxx << std::endl;
std::cout << xxx << std::endl;
return ;
}
- 全局變量特點:
全局變量默認是有外部鏈接性的,作用域是整個工程,在一個文件內定義的全局變量,在另一個文件中,通過 extern 全局變量名的聲明,就可以使用全局變量。
- 靜態(tài)全局變量特點:
全局靜態(tài)變量是顯式用 static 修飾的全局變量,作用域是聲明此變量所在的文件,其他的文件即使用 extern 聲明也不能使用。
2. 在函數中定義的靜態(tài)局部變量
在函數中定義的靜態(tài)變量僅僅初始化一次,且變量會存儲到靜態(tài)存儲區(qū),因此即便離開函數作用域也不會消失。
// c.h
#include<iostream>
#include<string>
class C
{
public:
C(std::string n):name(n)
{
std::cout << "constructor C " << std::endl;
}
~C(){
std::cout << "destructor C " << std::endl;
}
std::string getName()
{
return this->name;
}
private:
std::string name;
};
// main.cpp
#include<iostream>
#include"c.h"
void testStatic()
{
static int count = 0; // 只會被初始化一次
cout << "count: " << count++ << endl; // 每次調用該函數都會將上次存儲的值打印出來
}
C& getTestStaticC()
{
static C c("I'm static object."); // 只初始化一次,生命周期與程序等長
return c;
}
int main()
{
testStatic();
testStatic();
testStatic();
C& cc1 = getTestStaticC(); // 因為定義的靜態(tài)變量存儲在靜態(tài)存儲區(qū),不是在棧上,因此離開函數作用域以后,對靜態(tài)的引用仍然是可以訪問的
C& cc2 = getTestStaticC(); // 因為定義的靜態(tài)變量存儲在靜態(tài)存儲區(qū),不是在棧上,因此離開函數作用域以后,對靜態(tài)的引用仍然是可以訪問的
std::cout << "cc1: " << cc1.getName() << std::endl;
std::cout << "cc2: " << cc2.getName() << std::endl;
C cc3("666888");
return 0;
}
輸出:
3. 類的靜態(tài)成員變量
類的靜態(tài)成員變量屬于類的所有對象,其存儲在靜態(tài)存儲區(qū),只有一個存儲空間;而其他的非靜態(tài)變量屬于每個對象,在每個對象中都有其副本。
靜態(tài)成員變量不在構造函數中初始化,因此靜態(tài)成員變量不依賴于對象。
靜態(tài)成員變量必須顯示的初始化,一般情況下,我們都在類的外部對靜態(tài)成員變量初始化,若是靜態(tài)成員變量未被初始化,編譯鏈接時,會報錯。
// c.h
#include<iostream>
#include<string>
class C
{
public:
C(std::string n):name(n)
{
std::cout << "constructor C name: " << this->name << std::endl;
}
~C(){
std::cout << "destructor C name: " << this->name << std::endl;
}
std::string getName()
{
return this->name;
}
private:
public:
std::string name;
static int height;
};
// c.cpp
#include "c.h"
int C::height = 66; // 靜態(tài)成員變量需要顯示的定義在類的外部
// main.cpp
#include"c.h"
#include<iostream>
int& testStatic21()
{
C c("static21 test");
std::cout << "name: " << c.getName() << " , height: " << c.height << std::endl;
return c.height;
}
std::string& testStatic22()
{
C c("static22 test");
std::cout << "name: " << c.getName() << " , height: " << c.height << std::endl;
return c.name;
}
int main()
{
int& abc = testStatic21();
std::cout << "abc: " << abc << std::endl; // 因為存儲在靜態(tài)存儲區(qū),所以離開函數作用域后,變量仍然存在
std::string& name = testStatic22();
std::cout << "name: " << name << std::endl; // 非靜態(tài)成員變量實際存儲位置是函數的??臻g中,因此離開函數作用域后,就會被釋放掉,所以獲取結果未可知
return 0;
}
輸出:
4. 靜態(tài)類對象
static
?關鍵字對類對象的工作方式也相同。聲明為?static
?的對象將分配到靜態(tài)存儲區(qū)中,并且一直作用到程序結束。
注:使用?
static
?關鍵字分配為零僅適用于原始數據類型,不適用于用戶定義的數據類型。
// c.h
#include<iostream>
#include<string>
class C
{
public:
C(std::string n):name(n)
{
std::cout << "constructor C name: " << this->name << std::endl;
}
~C(){
std::cout << "destructor C name: " << this->name << std::endl;
}
std::string getName()
{
return this->name;
}
private:
public:
std::string name;
};
// main.cpp
int main()
{
C& cc = testStatic3();
std::cout << "cc: " << cc.getName() << std::endl; // 靜態(tài)對象存儲在靜態(tài)存儲區(qū), 所以離開函數作用域后,仍然存在
return 0.
}
輸出:
5. 類的靜態(tài)方法
與類的靜態(tài)成員變量類似,類的靜態(tài)方法也屬于類,任何類的對象都可以調用此類方法。
既可以通過 對象名. 靜態(tài)方法 調用,也可以通過類名::靜態(tài)方法,后一種方法更常用。
// c.h
#include<iostream>
#include<string>
class C
{
public:
C(std::string n):name(n)
{
std::cout << "constructor C name: " << this->name << std::endl;
}
~C(){
std::cout << "destructor C name: " << this->name << std::endl;
}
std::string getName()
{
return this->name;
}
static void print()
{
std::cout << "print height: " << height << std::endl;
}
private:
public:
std::string name;
static int height;
};
// c.cpp
#include "c.h"
int C::height = 66;
// main.cpp
#include"c.h"
#include<iostream>
void testStatic4()
{
C::print();
C c("888");
c.print();
}
int main()
{
testStatic4();
return 0;
}
二? ? static 變量幾種初始化方式
C++中static變量的初始化_c++ static 重新初始化_LikeMarch的博客-CSDN博客
三種初始化:
1. 編譯時初始化
2. 程序加載時初始化
3. 運行時初始化
1. 編譯時初始化
若?靜態(tài)全局變量?是 基本數據類型(POD) ,且初始化值為常量,那么該變量會在編譯期初始化。
/ main.cpp
static int xx = 666;
int main()
{
return 0;
}
2. 程序加載時初始化
程序被加載時立即初始化,該過程發(fā)生在main 函數執(zhí)行前。即使程序任何地方都沒訪問過該變量,仍然會進行初始化,因此形象地稱之為"餓漢式初始化"。
2.1? 靜態(tài)全局變量初始化(初始值不是常量時),此時變量初始化是在程序加載時初始化的。
// main.cpp
int x = 6;
int y = 8;
static int z = x + y;
int main()
{
return 0;
}
2.2? 靜態(tài)全局變量不是基本類型,此時變量初始化是在程序加載時初始化的。
// d.h
#include<iostream>
#include<string>
class D
{
public:
D(std::string n):name(n)
{
std::cout << "constructor D name: " << this->name << std::endl;
}
~D()
{
std::cout << "destructor D name: " << this->name << std::endl;
}
private:
std::string name;
};
// c.h
class C
{
public:
C(std::string n):name(n)
{
std::cout << "constructor C name: " << this->name << std::endl;
}
~C(){
std::cout << "destructor C name: " << this->name << std::endl;
}
std::string getName()
{
return this->name;
}
static void print()
{
std::cout << "print height: " << height << std::endl;
}
private:
public:
std::string name;
static int height;
static D d;
};
// c.cpp
int C::height = 66;
D C::d = D("CD static");
// main.cpp
#include<string>
#include<iostream>
#include"c.h"
void testStatic5()
{
C c("testStatic5 -- ");
std::cout << "testStatic5 c name: " << c.getName() << std::endl;
}
static D d("before main inialiaze!");
int main()
{
std::cout << "enter int main func!!" << std::endl;
testStatic5();
return 0;
}
3. 運行時初始化
程序執(zhí)行到靜態(tài)變量的定義引用時,才會初始化,因此也被稱為“懶漢式初始化”。
比如靜態(tài)局部變量就是典型的?運行時初始化。
// d.h
class D
{
public:
D(std::string n):name(n)
{
std::cout << "constructor D name: " << this->name << std::endl;
}
~D()
{
std::cout << "destructor D name: " << this->name << std::endl;
}
public:
std::string name;
};
// main.cpp
#include<iostream>
#include"d.h"
void testStaticInitialize(){
static D d("testStaticInitialize --- ");
}
int main()
{
std::cout << "enter int main func!!" << std::endl;
static D dd("dd --- ");
testStaticInitialize();
return 0;
}
輸出:文章來源:http://www.zghlxwxcb.cn/news/detail-705797.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-705797.html
到了這里,關于C++ -- 學習系列 static 關鍵字的使用的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!