これは実際には説明するのが本当に難しいものですが、私はそれをやってみましょう...
まず、dimof
あなたに伝え次元、または配列の要素数を。(「ディメンション」は、Windowsプログラミング環境で推奨される用語です)。
これは必要であるC++
とC
あなたに配列のサイズを決定するためのネイティブな方法を与えることはありません。
多くの場合、人々sizeof(myArray)
はうまくいくと思っていますが、実際には要素の数ではなく、メモリ内のサイズがわかります。各要素はおそらく1バイト以上のメモリを使用します!
次に、彼らは試みるかもしれませんsizeof(myArray) / sizeof(myArray[0])
。これにより、配列のメモリ内のサイズが、最初の要素のサイズで除算されます。これは問題なく、C
コードで広く使用されています。これの主な問題は、配列ではなくポインタを渡した場合に機能するように見えることです。メモリ内のポインタのサイズは、それが指すものが数千の要素の配列である場合でも、通常4バイトまたは8バイトです。
したがって、次に試すことC++
は、テンプレートを使用して、配列に対してのみ機能するものを強制し、ポインタでコンパイラエラーを発生させることです。次のようになります。
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
テンプレートは配列でのみ機能します。型(実際には必要ありませんが、テンプレートを機能させるために存在する必要があります)と配列のサイズを推定し、サイズを返します。テンプレートの記述方法では、ポインターを使用できない可能性があります。
通常、ここで停止できます。これは、C ++標準ライブラリにありstd::size
ます。
警告:以下で、それは毛深い言語弁護士の領域に入ります。
これはかなりクールですが、あいまいなエッジケースでも失敗します。
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
配列x
は宣言されていますが、定義されていないことに注意してください。関数(つまりArraySize
)を呼び出すには、を定義するx
必要があります。
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
これはリンクできません。
問題のコードはその回避策です。実際に関数を呼び出す代わりに、正確なサイズのオブジェクトを返す関数を宣言します。次に、そのsizeof
トリックを使用します。
関数を呼び出すように見えますが、これsizeof
は純粋にコンパイル時の構造であるため、関数が実際に呼び出されることはありません。
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^ ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes
関数から配列を実際に返すことはできませんが、配列への参照を返すことはできます。
次にDimofSizeHelper(myArray)
である式そのタイプにアレイであるN
char
Sは。式は実際に実行可能である必要はありませんが、コンパイル時に意味があります。
したがってsizeof(DimofSizeHelper(myArray))
、実際に関数を呼び出した場合に得られるであろうコンパイル時のサイズがわかります。実際にそれを呼び出すわけではありませんが。
最後のブロックが意味を成さなくても心配しないでください。奇妙なエッジケースを回避するのは奇妙なトリックです。このため、この種のコードを自分で記述せず、ライブラリの実装者にこの種のナンセンスを心配させます。
std::array
std::vector