面接---constと#defineの違い
4282 ワード
C++言語はconstで定数を定義してもよいし、#defineで定数を定義してもよい.しかし、前者は後者よりも多くの利点があります.
(1)const定数にはデータ型があり,マクロ定数にはデータ型がない.コンパイラは、前者のタイプのセキュリティチェックを行うことができます.一方、後者は文字置換のみを行い、タイプセキュリティチェックはなく、文字置換で予想外のエラー(境界効果)が発生する可能性があります.
(2)統合されたデバッグツールによってはconst定数をデバッグできますが、マクロ定数をデバッグできません.
(3)C++プログラムではマクロ定数を用いずにconst定数のみを用いる,すなわちconst定数はマクロ定数を完全に置換する.
(4)クラスの定数
いくつかの定数がクラスでのみ有効であることを望む場合があります.#defineで定義されたマクロ定数はグローバルであり,目的を達成できないため,const修飾データメンバーで実現すべきであると考えるのは当然である.constデータメンバーは確かに存在しますが、その意味は私たちが望んでいるものではありません.constデータ・メンバーは、オブジェクトの生存期間内にのみ定数であり、クラス全体に対して可変です.クラスは複数のオブジェクトを作成でき、異なるオブジェクトはconstデータ・メンバーの値が異なるためです.
クラス宣言でconstデータメンバーを初期化できません!!!クラスのオブジェクトが作成されていない場合、コンパイラはSIZEの値が何であるか分からないため、以下の使い方は間違っています.
constデータメンバーの初期化はクラス構造関数の初期化テーブルでのみ行うことができます!!!たとえば
結果:
クラス全体で一定の定数を確立するにはどうすればいいですか?constデータメンバーを期待しないで、クラスの列挙定数で実現するべきです.たとえば
列挙定数は、オブジェクトのストレージ領域を占有せず、コンパイル時にすべて評価されます.列挙定数の欠点は、隠しデータ型が整数であり、最大値が限られており、浮動小数点数(例えばPI=3.14159)を表すことができないことです.
(5)c++プログラムでは,クラス内のデータメンバーにmutableを加えるとconstのメンバー関数に修飾して修正できる.
まとめ
(1)コンパイラ処理方式が異なるdefineマクロは,前処理段階で展開される.const定数はコンパイル実行フェーズで使用されます.(2)タイプとセキュリティチェックが異なるdefineマクロにはタイプがなく,タイプチェックは一切せず,展開のみである.const定数には特定のタイプがあり、コンパイルフェーズでタイプチェックが実行されます.(3)記憶方式が異なるdefineマクロは展開するだけで,どこで使うか,何度展開するか,メモリは割り当てられない.const定数はメモリに割り当てられます(スタック内でもスタック内でも構いません).
(4)constは不要なメモリ割り当てを回避するためにスペースを節約できる.例:#define PI 3.14159//定数マクロconst doulbe Pi=3.14159;このときPiをROMに入れなかった…double i=Pi;//この時点でPiにメモリを割り当て、以降は割り当てません!double I=PI;//コンパイル中にマクロ置換を行い、メモリdouble j=Piを割り当てる//メモリ割り当てdouble J=PI;//マクロの置き換えを行い、メモリを再割り当てします.const定義定数はアセンブリの観点から、#defineのように即時数ではなく、対応するメモリアドレスが与えられるだけであるため、const定義定数はプログラム実行中にコピーが1部しかなく、#define定義定数はメモリにいくつかのコピーがある.(5)効率が向上した.コンパイラは通常、通常のconst定数にストレージスペースを割り当てるのではなく、シンボルテーブルに保存します.これにより、コンパイル中の定数となり、ストレージとリードメモリの操作がなくなり、効率が向上します.
転載:http://blog.sina.com.cn/s/blog_79b01f6601018xdg.html
(1)const定数にはデータ型があり,マクロ定数にはデータ型がない.コンパイラは、前者のタイプのセキュリティチェックを行うことができます.一方、後者は文字置換のみを行い、タイプセキュリティチェックはなく、文字置換で予想外のエラー(境界効果)が発生する可能性があります.
(2)統合されたデバッグツールによってはconst定数をデバッグできますが、マクロ定数をデバッグできません.
(3)C++プログラムではマクロ定数を用いずにconst定数のみを用いる,すなわちconst定数はマクロ定数を完全に置換する.
(4)クラスの定数
いくつかの定数がクラスでのみ有効であることを望む場合があります.#defineで定義されたマクロ定数はグローバルであり,目的を達成できないため,const修飾データメンバーで実現すべきであると考えるのは当然である.constデータメンバーは確かに存在しますが、その意味は私たちが望んでいるものではありません.constデータ・メンバーは、オブジェクトの生存期間内にのみ定数であり、クラス全体に対して可変です.クラスは複数のオブジェクトを作成でき、異なるオブジェクトはconstデータ・メンバーの値が異なるためです.
クラス宣言でconstデータメンバーを初期化できません!!!クラスのオブジェクトが作成されていない場合、コンパイラはSIZEの値が何であるか分からないため、以下の使い方は間違っています.
class A {…
const int SIZE = 100; // , const
int array[SIZE]; // , SIZE
};
constデータメンバーの初期化はクラス構造関数の初期化テーブルでのみ行うことができます!!!たとえば
#include <iostream>
using namespace std;
class A
{
public:
A(int size); //
const int SIZE ;
};
A::A(int size) : SIZE(size) //
{
}
int main(void)
{
A a(100); // a SIZE 100
A b(200); // b SIZE 200
cout<<a.SIZE<<endl;
cout<<b.SIZE<<endl;
return 0;
}
結果:
100
200
Process returned 0 (0x0) execution time : 0.615 s
Press any key to continue.
クラス全体で一定の定数を確立するにはどうすればいいですか?constデータメンバーを期待しないで、クラスの列挙定数で実現するべきです.たとえば
class A {…
enum { SIZE1 = 100, SIZE2 = 200}; //
int array1[SIZE1];
int array2[SIZE2];
};
列挙定数は、オブジェクトのストレージ領域を占有せず、コンパイル時にすべて評価されます.列挙定数の欠点は、隠しデータ型が整数であり、最大値が限られており、浮動小数点数(例えばPI=3.14159)を表すことができないことです.
(5)c++プログラムでは,クラス内のデータメンバーにmutableを加えるとconstのメンバー関数に修飾して修正できる.
まとめ
(1)コンパイラ処理方式が異なるdefineマクロは,前処理段階で展開される.const定数はコンパイル実行フェーズで使用されます.(2)タイプとセキュリティチェックが異なるdefineマクロにはタイプがなく,タイプチェックは一切せず,展開のみである.const定数には特定のタイプがあり、コンパイルフェーズでタイプチェックが実行されます.(3)記憶方式が異なるdefineマクロは展開するだけで,どこで使うか,何度展開するか,メモリは割り当てられない.const定数はメモリに割り当てられます(スタック内でもスタック内でも構いません).
(4)constは不要なメモリ割り当てを回避するためにスペースを節約できる.例:#define PI 3.14159//定数マクロconst doulbe Pi=3.14159;このときPiをROMに入れなかった…double i=Pi;//この時点でPiにメモリを割り当て、以降は割り当てません!double I=PI;//コンパイル中にマクロ置換を行い、メモリdouble j=Piを割り当てる//メモリ割り当てdouble J=PI;//マクロの置き換えを行い、メモリを再割り当てします.const定義定数はアセンブリの観点から、#defineのように即時数ではなく、対応するメモリアドレスが与えられるだけであるため、const定義定数はプログラム実行中にコピーが1部しかなく、#define定義定数はメモリにいくつかのコピーがある.(5)効率が向上した.コンパイラは通常、通常のconst定数にストレージスペースを割り当てるのではなく、シンボルテーブルに保存します.これにより、コンパイル中の定数となり、ストレージとリードメモリの操作がなくなり、効率が向上します.
転載:http://blog.sina.com.cn/s/blog_79b01f6601018xdg.html