1. 程式人生 > >c++公共常量定義方式的比較

c++公共常量定義方式的比較

我們常在公共標頭檔案中定義一些常量,定義常量方法如下:

方法1
commdef.h(公共標頭檔案):

const int constname = XXX;

在使用該變數的地方加入 #include "commdef.h"

方法2
commdef.h(公共標頭檔案):

extern const int constname;

commdef.cpp檔案:

const int constname = XXX;

在使用該變數的地方加入 #include "commdef.h"

由於這兩種方式都編譯執行沒問題,所以程式設計師很少留意它們的區別。兩種方法的比較:

若新增刪除常量常量,用方法1更方便,只需在.h檔案中修改;若改變常量值,使用方法2的程式因不需要改標頭檔案,則更節省編譯時間。

若從記憶體使用上看,哪種更好?接下來測試看看。

測試程式定義了兩個模組,test1和test2,test1.cpp和test2.cpp都引用了commdef.h標頭檔案,使用了全域性常量,我們通過檢視各個模組的常量地址來確定是否另分配了記憶體。

環境:Windows + vs2005

// commdef.h檔案

#ifndef LX_COMMDEF_H
#define LX_COMMDEF_H

const int MAX_LENGTH = 1024;

extern const int MIN_LENGTH;

#endif

// commdef.cpp檔案

#include "commdef.h"

const int MIN_LENGTH = 10;

// test1.cpp檔案(注:標頭檔案內容由於簡單所以省略掉了)

#include "commdef.h"
#include "test1.h"
#include <iostream>
using namespace std;

void FuncTest1()
{
  cout << "MAX_LENGTH = " << MAX_LENGTH << ", address: " << &MAX_LENGTH << endl;
  cout << "MIN_LENGTH = " << MIN_LENGTH << ", address: " << &MIN_LENGTH << endl;
}

// test2.cpp檔案(注:標頭檔案內容由於簡單所以省略掉了)

#include "commdef.h"
#include "test1.h"
#include <iostream>
using namespace std;

void FuncTest2()
{
  cout << "MAX_LENGTH = " << MAX_LENGTH << ", address: " << &MAX_LENGTH << endl;
  cout << "MIN_LENGTH = " << MIN_LENGTH << ", address: " << &MIN_LENGTH << endl;
}

輸出:
MAX_LENGTH = 1024, address: 00437AE4
MIN_LENGTH = 10, address: 00437B54
MAX_LENGTH = 1024, address: 00437B1C
MIN_LENGTH = 10, address: 00437B54

可見,用方法1定義的常量在多個模組中是分別儲存的,用方法2定義的常量是在一處儲存的,所以,在儲存上,方法2要優於方法1。

特別是當常量多,標頭檔案被引用多的情況下尤其注意,定義不當會帶來不必要的記憶體浪費。

附上stackoverflow上找到的:
static in Objective-C means a different thing than static in a C++ class, in the context of static class data members and static class methods. In C and Objective-C, a static variable or function at global scope means that that symbol has internal linkage.


Internal linkage means that that symbol is local to the current translation unit, which is the current source file (.c or .m) being compiled and all of the header files that it recursively includes. That symbol cannot be referenced from a different translation unit, and you can have other symbols with internal linkage in other translation units with the same name.


So, if you have a header file declaring a variable as static, each source file that includes that header gets a separate global variable—all references to that variable within one source file will refer to the same variable, but references in different source files will refer to different variables.


If you want to have a single global variable, you can't have it in class scope like in C++. One option is to create a global variable with external linkage: declare the variable with the extern keyword in a header file, and then in one source file, define it at global scope without the extern keyword. Internal linkage and external linkage are mutually exclusive—you cannot have a variable declared as both extern and static.


An alternative, as Panos suggested, would be to use a class method instead of a variable. This keeps the functionality within the scope of the class, which makes more sense semantically, and you can also make it @private if you so desire. It does add a marginal performance penalty, but that's highly unlikely to be the bottleneck in your application (if you suspect it is, always profile first).