標籤:

如何理解C++中的關鍵字static, const, 以及#define在定義變數時的區別?

如題,他們有什麼區別和聯繫呢?使用的時候有哪些需要注意的細節?


#define和那兩個都不一樣,它屬於宏,是預處理器的一部分。預處理是在編譯之前的一道,簡單地進行字元串替換。它不按照語言的語法,而是直觀自己的語法。你#define裡面寫的東西會被簡單粗暴地塞進去:

#define FuckTwice fuck fuck

FuckTwice;

會得到:

fuck fuck;

編譯器會感覺你寫了一個變數,名字是fuck,類型是fuck。

const是單詞constant的簡寫,字面意思是常數、常量。用於變數修飾,表明這個變數不能被修改;用於指針修飾,表明指針的指向物不能被修改;用於方法修飾,表明這個方法不會對對象造成改變。

const int foo = 1;
foo = 2; // compile time error

const int* ptr = foo;
*ptr = 3 // compile time error

int fuck = 0;
ptr = fuck; // this is OK
*ptr = 123; // compile time error

struct FooBar
{
int member;
int MyMethod(int value) const
{
member = value; // compile time error
}
};

static很討厭,有三個個完全不同的含義:

用在全局變數,表明這個變數在每個編譯單元有獨自的實例:

// foo.h
static int a = 123;

// foo.cpp
#include "foo.h"
int foo_func() { return a++; }

// bar.cpp
#include "foo.h"
int bar_func() { return a++; }

如果你分別編譯foo.cpp和bar.cpp,再把它們鏈接在一起,全局變數a會有兩份,那兩個函數會操縱不一樣的a實例。

用在函數里的局部變數,表明它的生存周期其實是全局變數,但僅在函數內可見:

int get_global_id()
{
static int seed = 0;
return seed++;
}

每次訪問這個函數的時候,會獲得不同的int值。那個=0的操作僅在第一次訪問時執行,其實是初始化而不是賦值。

用在類成員,表明成員或者方法是類的,而不是對象實例的。

struct Foo
{
int a = 0;
static int aaa = 0;
static int bbb() { return 123456; }
};

每個Foo實例會只含有一個int a。bbb方法通過Foo::bbb()調用。


http://www.jnydkj.cn/News/Industry/2013/1226/98.html

CC++裡面的static:

面向過程的static:

在c和c++面向過程的設計里,在全局變數前加上static關鍵字則可將該變數定義為一個靜態全局變數,比如:

static int a;

那麼c和c++中的靜態全局變數有什麼特點呢:

1、 變數在全局數據區分配內存(局部變數在棧內,通過new和malloc動態分配的變數在堆里);

2、 未經初始化的全局變數會被程序自動初始化為0;

3、 靜態全局變數或函數在聲明它的文件內是可見的,在文件外是不可見的;(可以起到保護作用)

講講第三點,如果我們只是在某個頭文件中聲明了一個普通的全局變數a,那麼在引用這個頭文件的時候,我們也可以通過extern關鍵字將這個變數引用到當前文件中;但是如果你在聲明那個變數的時候就加了static關鍵字,那麼全局變數a對於其他任何文件都是不可見的。

同樣的,如果以static方式定義了一個函數,那麼這個函數只在定義它的文件內可見。

面向對象的static:

在面向對象設計裡面,使用static有幾點要注意:

1、 靜態成員函數的聲明在類內要加上static關鍵字,但是在類外實現的時候不需要;

2、 靜態成員函數沒有this指針,所以不要嘗試顯示或隱式地在靜態成員函數內引用這個指針,這種做法會導致編譯期間報錯。因此也就不要嘗試些什麼在構造函數中給靜態成員變數初始化的動作了。

下面寫個小例子感受一下面向對象的static:

首先定義一個頭文件account.h,在頭文件中定義一個類:

#pragma once

class Account

{

public:

static void reiseInterest(double var );

static double interest(){return dInterest; } //類內給出實現,語句簡單,無遞歸,與類外實現並聲明為inline函數都是相同的,均為內聯函數

private:

static double dInterest ;

};

double Account::dInterest = 5; //靜態數據成員初始化

inline void Account::reiseInterest(double var)

{

dInterest += var;

}

接著在源文件中進行測試:

#include &

#include "account.h"

using namespace std;

int main()

{

//double Account::dInterest = 5; //錯誤!!static關鍵字限制了可視域!!

cout&<&<"The initial interest is "&<& Account ac1;

Account ac2;

ac1.reiseInterest(18);

ac2.reiseInterest(17);

cout&<&<"The current interest is "&<&

return 0;

}

運行結果如下:


他們沒有聯繫只有區別:不同層面上的東西。

  • #define: 預處理層面上的替換,不存在於語意層面

  • static: 變數的作用域控制
  • const: 變數的訪問控制:只讀


這三個是完全不同的東西

其中static用於在類中聲明類方法或類變數,或者在函數中聲明靜態變數(在該函數的多次調用中指向同一內存區域的變數),似乎還有別的類似用處,記不清了。

const用於聲明常量,就是不可改變的量。而上面的static變數是可以改變的。對常量的改變會導致編譯器報錯。常量是會在棧上分配空間的。

define表面上跟const很像,但實質完全不同。它是一個繼承自C的機制,叫做宏。它做的事情是純粹的字元串替換,而不會分配空間。宏能完成比const複雜得多的工作。雖然在effective C++里貌似不推薦使用宏


推薦閱讀:

智能指針有什麼不足之處?
有講C/C++代碼優化和編譯器優化的書或文章嗎?
像c++ primer這樣的計算機專業書籍,大家都是在那裡買的,報價都不便宜啊?
c/c++開發轉嵌入式(軟體/驅動)工程師好轉嗎?
mfc中CString如何轉化為const char*類型?

TAG:C | CC |