C++ 面接問題集:ポインタ、配列、const の基礎

1. for ループと while ループの変換

for 文は while 文に書き換え可能である。同様に do-while 文でも実現できる。条件判定のタイミングが異なるが、制御構造の本質は同じである。C++ ではループ制御の書き換えが容易であり、可読性向上のために適宜選択する。

2. 二次元配列の文字列出力

#include <cstring>
#include <cstdio>

int main() {
    char data[2][4];
    strcpy(data[0], "you");
    strcpy(data[1], "me");
    data[0][3] = '&';
    printf("%s\n", data);
    return 0;
}

出力: you&me
二次元配列は行優先でメモリに配置される。data[0] には "you\0" が格納され、data[1] には "me\0" が格納される。3番目の要素に '&' を代入すると、ヌル文字が上書きされるため、文字列は "you&me" として連結される。配列名は先頭アドレスを指す。

3. const キーワードの処理時期

const int i = 10; のような宣言は「コンパイル時」に処理される。コンパイラは定数値をシンボルテーブルに記録し、以降の参照を直接値で置き換える(マクロ類似)。これにより、実行時のメモリアクセスが不要となり、読み取り専用の保証が得られる。

4. 演算子オーバーロードの制約

演算子をオーバーロードしても、元の優先順位や結合性は変更できない。また、オペランドの個数も変えられず、少なくとも1つはユーザ定義型でなければならない。構文構造(前置・後置など)も維持する。戻り値型や引数の型は自由に指定できる。

5. ポインタのサイズ(32ビットシステム)

void *p = malloc(100);
sizeof(p); // 結果: 4

32ビットシステムではポインタは4バイト、64ビットでは8バイトとなる。常に int と同じサイズとは限らないが、多くのプラットフォームで一致する。

6. ポインタの値渡しと静的変数

void modify(int *ptr) {
    static int value = 4;
    ptr = &value;
    (*ptr)--;
}

int main() {
    int num = 5;
    int *ptr = &num;
    modify(ptr);
    printf("%d", *ptr); // 出力: 5
    return 0;
}

ポインタを関数に渡す場合も「値渡し」である。関数内で ptr に新しいアドレスを代入しても、呼び出し元の ptr は影響を受けない。静的変数 value はデクリメントされるが、呼び出し元のポインタは元の num を指したままである。

7. オブジェクト指向プログラミングの利点

主な利点: 再利用性(継承)、拡張性(ポリモーフィズム)、保守性(カプセル化)、理解の容易さ。三大特性は「継承」「カプセル化」「ポリモーフィズム」である。

8. 配列とポインタの違い

  • A: 配列は静的領域(グローバル)またはスタックに作成される。ヒープには動的配列として確保できる。
  • B: sizeof(配列名) は配列全体のバイト数を返す。正しい。
  • C: ポインタは任意の型を指せるが、const 修飾により再代入不可のポインタもある(例: char* const p)。
  • D: sizeof(ポインタ) はポインタ変数自体のサイズであり、指す先の容量ではない(例: char* str = "hello"; sizeof(str) // 4 または 8)。

正解: B

タグ: C++ ポインタ 配列 const 演算子オーバーロード

6月12日 18:56 投稿