最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于C++全局變量的聲明與定義的詳解

 更新時間:2013年05月30日 17:40:23   作者:  
本篇文章是對C++全局變量的聲明與定義進行了詳細的分析介紹,需要的朋友參考下
(1)編譯單元(模塊)
在VC或VS上編寫完代碼,點擊編譯按鈕準備生成exe文件時,編譯器做了兩步工作:
第一步,將每個.cpp(.c)和相應的.h文件編譯成obj文件;
第二步,將工程中所有的obj文件進行LINK,生成最終.exe文件。
那么,錯誤可能在兩個地方產(chǎn)生:
一個,編譯時的錯誤,這個主要是語法錯誤;
一個,鏈接時的錯誤,主要是重復定義變量等。
編譯單元指在編譯階段生成的每個obj文件。
一個obj文件就是一個編譯單元。
一個.cpp(.c)和它相應的.h文件共同組成了一個編譯單元。
一個工程由很多編譯單元組成,每個obj文件里包含了變量存儲的相對地址等。
(2)聲明與定義
函數(shù)或變量在聲明時,并沒有給它實際的物理內(nèi)存空間,它有時候可保證你的程序編譯通過;
函數(shù)或變量在定義時,它就在內(nèi)存中有了實際的物理空間。

如果你在編譯單元中引用的外部變量沒有在整個工程中任何一個地方定義的話,那么即使它在編譯時可以通過,在連接時也會報錯,因為程序在內(nèi)存中找不到這個變量。
函數(shù)或變量可以聲明多次,但定義只能有一次。
(3) extern作用
作用一:
當它與"C"一起連用時,如extern "C" void fun(int a, int b);,則編譯器在編譯fun這個函數(shù)名時按C的規(guī)則去翻譯相應的函數(shù)名而不是C++的。
作用二:當它不與"C"在一起修飾變量或函數(shù)時,如在頭文件中,extern int g_nNum;,它的作用就是聲明函數(shù)或變量的作用范圍的關(guān)鍵字,其聲明的函數(shù)和變量可以在本編譯單元或其他編譯單元中使用。
即B編譯單元要引用A編譯單元中定義的全局變量或函數(shù)時,B編譯單元只要包含A編譯單元的頭文件即可,在編譯階段,B編譯單元雖然找不到該函數(shù)或變量,但它不會報錯,它會在鏈接時從A編譯單元生成的目標代碼中找到此函數(shù)。
(4)全局變量(extern)
有兩個類都需要使用共同的變量,我們將這些變量定義為全局變量。比如,res.h和res.cpp分別來聲明和定義全局變量,類ProducerThread和ConsumerThread來使用全局變量。(以下是QT工程代碼)
復制代碼 代碼如下:

/**********res.h聲明全局變量************/ 
#pragma once 

#include <QSemaphore> 

const int g_nDataSize = 1000; // 生產(chǎn)者生產(chǎn)的總數(shù)據(jù)量 
const int g_nBufferSize = 500; // 環(huán)形緩沖區(qū)的大小 

extern char g_szBuffer[]; // 環(huán)形緩沖區(qū) 
extern QSemaphore g_qsemFreeBytes; // 控制環(huán)形緩沖區(qū)的空閑區(qū)(指生產(chǎn)者還沒填充數(shù)據(jù)的區(qū)域,或者消費者已經(jīng)讀取過的區(qū)域) 
extern QSemaphore g_qsemUsedBytes; // 控制環(huán)形緩沖區(qū)中的使用區(qū)(指生產(chǎn)者已填充數(shù)據(jù),但消費者沒有讀取的區(qū)域) 
/**************************/ 

上述代碼中g(shù)_nDataSize、g_nBufferSize為全局常量,其他為全局變量。
復制代碼 代碼如下:

/**********res.cpp定義全局變量************/ 
#pragma once 
#include "res.h" 

// 定義全局變量 
char g_szBuffer[g_nBufferSize]; 
QSemaphore g_qsemFreeBytes(g_nBufferSize); 
QSemaphore g_qsemUsedBytes; 
/**************************/ 

在其他編譯單元中使用全局變量時只要包含其所在頭文件即可。
復制代碼 代碼如下:

/**********類ConsumerThread使用全局變量************/ 
#include "consumerthread.h" 
#include "res.h" 
#include <QDebug> 
ConsumerThread::ConsumerThread(QObject* parent) 
: QThread(parent) { 

ConsumerThread::ConsumerThread() { 


ConsumerThread::~ConsumerThread() { 

void ConsumerThread::run() { 
 for (int i = 0; i < g_nDataSize; i++) { 
  g_qsemUsedBytes.acquire();
  qDebug()<<"Consumer "<<g_szBuffer[i % g_nBufferSize]; 
  g_szBuffer[i % g_nBufferSize] = ' '; 
  g_qsemFreeBytes.release(); 
 } 
 qDebug()<<"&&Consumer Over"; 

/**************************/ 

也可以把全局變量的聲明和定義放在一起,這樣可以防止忘記了定義,如上面的extern char g_szBuffer[g_nBufferSize]; 然后把引用它的文件中的#include "res.h"換成extern char g_szBuffer[];。
但是這樣做很不好,因為你無法使用#include "res.h"(使用它,若達到兩次及以上,就出現(xiàn)重定義錯誤;注:即使在res.h中加#pragma once,或#ifndef也會出現(xiàn)重復定義,因為每個編譯單元是單獨的,都會對它各自進行定義),那么res.h聲明的其他函數(shù)或變量,你也就無法使用了,除非也都用extern修飾,這樣太麻煩,所以還是推薦使用.h中聲明,.cpp中定義的做法。
(5)靜態(tài)全局變量(static)
注意使用static修飾變量,就不能使用extern來修飾,即staticextern不可同時出現(xiàn)。
static修飾的全局變量的聲明與定義同時進行,即當你在頭文件中使用static聲明了全局變量,同時它也被定義了。
static修飾的全局變量的作用域只能是本身的編譯單元。在其他編譯單元使用它時,只是簡單的把其值復制給了其他編譯單元,其他編譯單元會另外開個內(nèi)存保存它,在其他編譯單元對它的修改并不影響本身在定義時的值。即在其他編譯單元A使用它時,它所在的物理地址,和其他編譯單元B使用它時,它所在的物理地址不一樣,A和B對它所做的修改都不能傳遞給對方。
多個地方引用靜態(tài)全局變量所在的頭文件,不會出現(xiàn)重定義錯誤,因為在每個編譯單元都對它開辟了額外的空間進行存儲。
以下是Windows控制臺應用程序代碼示例:
復制代碼 代碼如下:

/***********res.h**********/ 
static char g_szBuffer[6] = "12345"; 
void fun(); 
/************************/ 

復制代碼 代碼如下:

/***********res.cpp**********/ 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun() { 
 for (int i = 0; i < 6; i++) { 
  g_szBuffer[i] = 'A' + i; 
 } 
 cout<<g_szBuffer<<endl; 

/************************/ 

復制代碼 代碼如下:

/***********test1.h**********/ 
void fun1(); 
/************************/ 

復制代碼 代碼如下:

/***********test1.cpp**********/ 
#include "test1.h" 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun1() { 
fun(); 

 for (int i = 0; i < 6; i++) { 
  g_szBuffer[i] = 'a' + i; 
 } 
 cout<<g_szBuffer<<endl; 

/************************/ 

復制代碼 代碼如下:

/***********test2.h**********/ 
void fun2(); 
/************************/ 

復制代碼 代碼如下:

/***********test2.cpp**********/ 
#include "test2.h" 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun2() { 
 cout<<g_szBuffer<<endl; 

/************************/ 

復制代碼 代碼如下:

/***********main.cpp**********/ 
#include "test1.h" 
#include "test2.h" 

int main() { 
 fun1(); 
 fun2(); 

 system("PAUSE"); 
 return 0; 

/************************/ 

運行結(jié)果如下:


按我們的直觀印象,認為fun1()和fun2()輸出的結(jié)果都為abcdef,可實際上fun2()輸出的確是初始值。然后我們再跟蹤調(diào)試,發(fā)現(xiàn)res、test1、test2中g(shù)_szBuffer的地址都不一樣,分別為0x0041a020、0x0041a084、0x0041a040,這就解釋了為什么不一樣。
注:一般定義static 全局變量時,都把它放在.cpp文件中而不是.h文件中,這樣就不會給其他編譯單元造成不必要的信息污染。
(6)全局常量(const)
const單獨使用時,其特性與static一樣(每個編譯單元中地址都不一樣,不過因為是常量,也不能修改,所以就沒有多大關(guān)系)。
const與extern一起使用時,其特性與extern一樣。
[code]
extern const char g_szBuffer[];      //寫入 .h中 
const char g_szBuffer[] = "123456"; // 寫入.cpp中 
[/code

相關(guān)文章

  • C++的命名空間詳解

    C++的命名空間詳解

    這篇文章主要介紹了C++編程中的命名空間基本知識講解,包括對C++中內(nèi)聯(lián)命名空間新特性的介紹,需要的朋友可以參考下
    2021-09-09
  • C++實現(xiàn)LeetCode(67.二進制數(shù)相加)

    C++實現(xiàn)LeetCode(67.二進制數(shù)相加)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(67.二進制數(shù)相加),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++ list-map鏈表與映射表的簡單使用

    C++ list-map鏈表與映射表的簡單使用

    本文主要介紹了C++ list-map鏈表與映射表的簡單使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-05-05
  • C語言實踐設計開發(fā)飛機游戲

    C語言實踐設計開發(fā)飛機游戲

    飛機大戰(zhàn)想必是很多人童年時期的經(jīng)典游戲,我們依舊能記得抱個老人機娛樂的場景,下面這篇文章主要給大家介紹了關(guān)于如何利用C語言寫一個簡單的飛機大戰(zhàn)小游戲的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Qt界面美化之自定義qss樣式表的詳細步驟

    Qt界面美化之自定義qss樣式表的詳細步驟

    很多人應該和我一樣,想做界面才接觸的Qt,結(jié)果就是做不出來華麗的界面,下面這篇文章主要給大家介紹了關(guān)于Qt界面美化之自定義qss樣式表的詳細步驟,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • C語言數(shù)據(jù)輸入與輸出實例詳解

    C語言數(shù)據(jù)輸入與輸出實例詳解

    這篇文章主要介紹了C語言數(shù)據(jù)輸入與輸出實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++ Qt QColorDialog使用方法

    C++ Qt QColorDialog使用方法

    本文主要介紹了C++ Qt QColorDialog使用方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C++?this原理與可變參數(shù)及友元函數(shù)友元類分步詳解用法

    C++?this原理與可變參數(shù)及友元函數(shù)友元類分步詳解用法

    可變參數(shù)模板(variadic?templates)是C++11新增的強大的特性之一,它對模板參數(shù)進行了高度泛化,能表示0到任意個數(shù)、任意類型的參數(shù),這篇文章主要介紹了C++?this原理與可變參數(shù)及友元函數(shù)友元類
    2022-11-11
  • 詳解C語言中index()函數(shù)和rindex()函數(shù)的用法

    詳解C語言中index()函數(shù)和rindex()函數(shù)的用法

    這篇文章主要介紹了C語言中index()函數(shù)和rndex()函數(shù)的用法,是C語言入門學習中的基礎(chǔ)知識,要的朋友可以參考下
    2015-08-08
  • OpenCV圖像特征提取之Shi-Tomasi角點檢測算法詳解

    OpenCV圖像特征提取之Shi-Tomasi角點檢測算法詳解

    Harris角點檢測算法就是對角點響應函數(shù)R進行閾值處理,Shi-Tomasi原理幾乎和Harris一樣的,只不過最后計算角點響應的公式發(fā)生了變化。本文將和大家詳細說說Shi-Tomasi角點檢測算法的原理與實現(xiàn),需要的可以參考一下
    2022-09-09

最新評論

文化| 嘉祥县| 宁化县| 杨浦区| 南宁市| 英德市| 临汾市| 泰和县| 镇江市| 土默特左旗| 板桥市| 施秉县| 文昌市| 肇东市| 广河县| 织金县| 隆回县| 昌乐县| 乌什县| 望谟县| 邵武市| 孝昌县| 罗山县| 淮滨县| 西城区| 伊川县| 威远县| 壶关县| 民乐县| 岑溪市| 合江县| 南阳市| 白山市| 双流县| 平定县| 北辰区| 永安市| 远安县| 墨玉县| 永顺县| 彭山县|