網站制作詳細流程凈水器十大品牌
C語言和c++中的static關鍵字與const關鍵字
static: //改變存儲區(qū)域,限制作用域
①、改變存儲區(qū)域:
在不同的上下文中,static 關鍵字可以用于改變變量或函數(shù)的存儲區(qū)域。在函數(shù)內部,static 用于將局部變量的生存期從函數(shù)的生命周期擴展到整個程序的生命周期,并將其存儲在靜態(tài)存儲區(qū)中。
示例:
void foo() {static int count = 0; // 靜態(tài)局部變量count++;std::cout << "Count: " << count << std::endl;
}int main() {foo(); // 輸出:Count: 1foo(); // 輸出:Count: 2return 0;
}
②、限制作用域:
static 還可以用于限制變量、函數(shù)或類的作用域,使其僅在聲明它們的文件中可見,而不是跨越整個程序的多個文件。這種情況下,static 在全局變量、函數(shù)和類的上下文中使用。
示例:
Copy code
// File1.cpp
static int globalVar = 42; // 在當前文件中可見// File2.cpp
extern int globalVar; // 從另一個文件中訪問失敗,因為 globalVar 的作用域被限制在了 File1.cpp 中
在這個示例中,globalVar 被聲明為靜態(tài)全局變量,它的作用域限制在了聲明它的文件 File1.cpp 中,其他文件無法直接訪問。
一、C和c++中的static
static
1、修飾局部變量 //改變存儲區(qū)域: 棧區(qū)–>數(shù)據(jù)段 ,作用域:局部作用域
②C語言中static修飾的局部變量:
? 在修飾局部變量時,static修飾的靜態(tài)局部變量只執(zhí)行一次, 其會改變局部變量的存儲位置,從而使得局部變量的生命周期變長,直到程序運行結束以后才釋放。
void test()
{int x = 0;x++;printf("%d ", x);
}int main()
{int i = 0;while (i < 5){test();i++;}return 0;
}
//1 1 1 1 1
void test()
{static int x = 0;x++;printf("%d ", x);
}int main()
{int i = 0;while (i < 5){test();i++;}return 0;
}
//1 2 3 4 5
②c++中static修飾的局部變量:
局部變量也就是定義在函數(shù)內部的變量,函數(shù)局部變量存放在棧區(qū),該變量的生命周期由所在 {} 決定,進入 {} 作用范圍而分配內存空間,退出 {} 作用范圍而釋放內存空間。
在局部變量的前面加上static,變成靜態(tài)局部變量,即使多次調用該函數(shù),靜態(tài)變量的空間也只分配一次。
using namespace std;
void fun()
{static int n = 5;printf("%d\n", n);n++;
}
int main()
{int i;for(i=0; i<5; i++){fun();}return 0;
}
2、修飾全局變量 //限制作用域:外部鏈接屬性–>內部鏈接屬性
①C語言中的static修飾的全局變量
?static修飾全局變量的時, 會改變全局變量的鏈接屬性,從而使得全局變量作用域變?yōu)?u>只能在本文件中訪問,extern無法調用。
c文件1
int i = 10;
c文件2
extern int i;
int main()
{printf("%d\n",i);return 0;
}
如果全局變量被static修飾,那這個外部鏈接屬性就會被修改成內部鏈接屬性
②c++中static修飾的全局變量
全局變量的空間會在程序的生命周期內分配,在全局變量的前面加上static,變成靜態(tài)全局變量。
using namespace std;
static int n = 5;
int main()
{n = 10;printf("%d\n", n);return 0;
}
3、修飾函數(shù) //限制作用域:外部鏈接屬性–>內部鏈接屬性
①C語言中static修飾函數(shù)
?static修飾一個函數(shù),則這個函數(shù)的只能在本文件中調用,不能被其他文件調用。
?函數(shù)本身也是有外部鏈接屬性的,而被static修飾后,函數(shù)的外部鏈接屬性被修改成內部鏈接屬性。
c文件1
int Add(int a,int b)
{return x+y;
}
c文件2
extern int Add(int a,int b);
int main()
{int x = 3;int y = 4;int z = Add(x,y);printf("%d\n",z);return 0;
}
②c++中的static修飾函數(shù)
被static修飾的函數(shù),叫靜態(tài)函數(shù)。靜態(tài)函數(shù)只能在當前文件中被訪問,不可再其他文件中調用。其它文件中可以定義相同名字的函數(shù),不會發(fā)生沖突
4、在c++中static還可以修飾成員變量 :靜態(tài)成員變量, //不用通過對象調用, 所有對象共有的變量,
類的所有實體共享這個變量。
類的數(shù)據(jù)成員在類外定義時不加static。
class Test {
public:double d;static int n;
};int Test::n; // 靜態(tài)成員變量需要在類外聲明(分配空間,可以顯式初始化,默認初始化為0)cout << sizeof(Test) << endl;
cout << Test::n << endl;// 運行結果:8 0
靜態(tài)成員變量存儲在全局/靜態(tài)區(qū),靜態(tài)成員變量只有在類外聲明時才分配空間,可顯式初始化,不顯式初始化,默認初始化為0。
靜態(tài)成員變量屬于類不屬于對象,sizeof()的結果不包括靜態(tài)成員變量大小
可通過對象調用,也可以通過類名作用域調用(非靜態(tài)成員變量只能通過對象調用)
靜態(tài)常量整型數(shù)據(jù)成員可在類內初始化,也可在類外初始化
5、在c++中static還可以修飾成員函數(shù): 靜態(tài)成員函數(shù),靜態(tài)方法 //不用通過對象調用
靜態(tài)成員函數(shù)中只能調用靜態(tài)成員變量和靜態(tài)成員函數(shù)
類的靜態(tài)成員函數(shù)在類外實現(xiàn)時,與數(shù)據(jù)成員一樣不需要加 static
class Test {
public:static void show() {cout << n << endl;}private:double d;static int n;
};int Test::n;cout << sizeof(Test) << endl;
Test::show();// 運行結果:8 0
二、C和c++中的const
const:
const含義:只要一個變量前用const來修飾,就意味著該變量里的時數(shù)據(jù)只能被訪問,而不能被修改,也就是意味著“只讀”(readonly)
const在類中既可以修飾成員變量,也可以修飾成員函數(shù)本身,甚至還能修飾對象。
const作用:
1:可以用來修飾變量,修飾函數(shù)參數(shù),修飾函數(shù)返回值,且被const修飾的東西,都受到強制保護,可以預防其它代碼無意識的進行修改,從而提高了程序的健壯性
2:使編譯器保護那些不希望被修改的參數(shù),防止無意代碼的修改
3:增強代碼的可讀性
1、修飾變量
此時變量只能使用不可修改,直接修改(編譯報錯)與修改地址(程序異常)都不行
int main() {const int a = 20 ;printf("a = %d\n",a);a = 200 ;//errprintf("a = %d\n",a);return 0;
}
2、修飾指針變量類型(常量指針)
const修飾指針變量的類型,不可修改指針指向的地址里的內容(編譯報錯),可以修改指針的指向
void test()
{int c = 100;const int *p = &c;printf("c = %d\n",c);//*p = 888;//不可修改指針指向的地址里的內容,編譯報錯//printf("c = %d\n",c);int d =999;p = &d;//可以修改指針的指向printf("*p = %d\n",*p);
}
int main(int argc, char *argv[])
{test();return 0;
}
3、修飾指針變量(指針常量)
可以修改指針指向地址的內容,但是不能修改指針的指向(編譯報錯)
void test()
{int c = 200;int * const p = &c;//const修飾指針,即指針常量printf("*p = %d\n",*p);*p = 888;//修改指針指向地址里的內容printf("*p = %d\n",*p);int d =999;//p = &d;//不能修改指針的指向,編譯報錯//printf("*p = %d\n",*p);}
int main(int argc, char *argv[])
{test();return 0 ;
}
4、既修飾指針變量類型又修飾指針(常量指針常量)
不能修改指針指向地址的內容,不能修改指針指向
void test()
{int c = 200;const int * const p = &c;//即修飾指針變量類型又修飾指針變量printf("*p = %d\n",*p);//*p = 888;//不能修改指針指向地址里的內容,編譯報錯//printf("*p = %d\n",*p);//int d =999;//p = &d;//不能修改指針指向,編譯報錯//printf("*p = %d\n",*p);
}
int main(int argc, char *argv[])
{test();return 0;
}
5、修飾函數(shù)返回值
如果給以“指針傳遞”方式的函數(shù)返回值加 const 修飾,那么函數(shù)返回值(即指針)的內容不能被修改,該返回值只能被賦給加 const 修飾的同類型指針。
const char * GetString(void);//如下語句將出現(xiàn)編譯錯誤:
//char *str = GetString();//正確的用法是
const char *str = GetString();
6、修飾函數(shù)參數(shù)
? 如果函數(shù)參數(shù)采用“指針傳遞”,那么加 const 修飾可以防止意外地改動該指針,起到保護作用。
? 如果參數(shù)作為輸出參數(shù),不論它是什么數(shù)據(jù)類型,也不論它采用“指針傳遞”還是“引用傳遞”,都不能加 const 修飾,否則該參數(shù)將失去輸出功能(因為有 const 修飾之后,不能改變他的值)。
? 如果參數(shù)作為輸入?yún)?shù),可以防止數(shù)據(jù)被改變,起到保護作用,增加程序的健壯性。
7、修飾類中的變量與函數(shù)
<1>修飾成員變量
對成員變量的修飾與修飾普通變量差不多,都是設置為只讀數(shù)據(jù),但是類中的const變量
只能 通過構造函數(shù)初始化列表進行初始化 或者 直接值,
using namespace std;
class A
{
public:A(int a):m_a(a){} //正常A(int a){ //報錯m_a = a;}
private:const int m_a; //成員變量 只讀 const變量
};
int main()
{A A1(1);
}
<2>修飾成員函數(shù)
?首先,const修飾成員函數(shù),保留了const修飾普通函數(shù)的用法;其次,增加了在成員函數(shù)的聲明后邊添加const的用法,表示成員函數(shù)內部無法修改成員變量。
using namespace std;
class A {
public:int a = 1;/*第一個const:表示返回指針指向不可被更改第二個const:參照const修飾變量的用法第三個const:表示該成員函數(shù)不可修改成員變量*/void show(const int* p) const ; //修飾函數(shù) cosnt函數(shù) : 函數(shù)不能修改變量
};void A::show(const int* p) const {a = 2;//報錯,被第三個const限制*p = 2;//報錯,被第二個const限制cout<<"a="<<a<<endl;cout<<"*p="<<*p<<endl;
}int main(){A a;int c = 2;const int *b = &c;b = a.show(b);*b = &c;//報錯,被第一個const限制
}
<3>修飾對象 類似于修飾變量
? 在實例化對象的時候,添加const關鍵字,就是const對象,const對象只能訪問類中的const成員變量和const成員函數(shù)。
const class object(params);
const class *p = new class(params); //兩種用法等價