C++ Learning

第14回 確認問題(道具を整える)

STEP 2 で扱った 参照・初期化・関数・namespace・pair/tuple・イテレータ の総合確認クイズです。全 12 問、カテゴリ別に採点されます。正解すると即座にスコアバーが伸び、全問終えると苦手カテゴリの分析も出ます。

進め方

スコア 0 / 12 回答済み 0 参照 init/nullptr 関数 namespace pair/tuple iterator
参照 参照と参照渡し 0 / 2

Q1 次のコードの出力は?

void f(int& x) { x = 99; } int a = 1; f(a); std::cout << a;
99
1
コンパイルエラー
未定義動作
int& は参照渡し。xa への参照なので、x = 99;a を書き換えます。値渡し void f(int x) だったら a は変わらず 1。

Q2 次のうち正しいのはどれ?

int& r; // 初期化なしでも OK
int& r = nullptr; // 空の参照
int a = 5; int& r = a; // a への参照
int a = 5, b = 7; int& r = a; r = b; // r を b への参照に変更
参照は必ず初期化が必要(①は NG)、nullptr 相当がない(②は NG)、途中で指す先を変更できない(④の代入は「r が指す先(= a)に b の値を代入」という意味になり、a が 7 になります)。③が正しい参照の作り方。
init/nullptr 初期化と nullptr 0 / 2

Q3 コンパイルエラーになるのはどれ?

int x = 3.14;
int x(3.14);
int x{3.14};
auto x = 3.14;
{} 初期化は「狭める変換(narrowing)」を禁止。double → int の切り捨てはエラーにしてくれる。①と②は暗黙変換で通ってしまう(x は 3 になる)のが {} より危険な理由です。④は auto で double 型に推論されるので問題なし。

Q4 ポインタが何も指していないことを表す C++11 以降の推奨値は?

NULL
nullptr
0
void*
nullptr はポインタ専用の特別な型(std::nullptr_t)を持ちます。NULL0 は整数と区別できずオーバーロード解決で誤マッチすることがあり非推奨。
関数 オーバーロード・デフォルト引数・引数渡し 0 / 3

Q5 オーバーロードとして成立するペアはどれ?

int f(int); と int f(int);
int f(int); と int f(double);
int f(int); と double f(int);
int f(int a); と int f(int b);
オーバーロードは引数の型/個数が違う必要があります。①は完全に同一、③は戻り値だけ違う(NG)、④は仮引数名が違うだけで型は同じ(NG)。②だけが合法。

Q6 void f(int a, int b = 0, int c); はコンパイルできる?

できる
できない(デフォルト引数のあとに非デフォルトがある)
警告のみで通る
b を自動で無視して通る
デフォルト引数は右(末尾)から連続して付ける必要があります。f(1, 2); の呼び出しで「b を省略して 2 を c に渡したのか」が決められないため。

Q7 std::string を「読むだけ」で関数に渡す最も良い書き方は?

void f(std::string s)
void f(std::string& s)
void f(std::string* s)
void f(const std::string& s)
const T& は「コピーなし(速い)」+「書き換え禁止(安全)」の両立。重い型を読むだけのときの既定の選択です。①は毎回コピーで遅い、②は意図せず書き換えの可能性、③はポインタで nullptr チェックが必要になり冗長。
namespace 名前空間 0 / 1

Q8 using namespace std; が本サイトで推奨されない主な理由は?

コンパイルが遅くなるから
std の識別子が自作関数や他ライブラリと衝突するリスクがあるから
規格で禁止されているから
実行時オーバーヘッドが発生するから
std には count / distance / size など一般的な名前が多く、自作のシンボルと衝突する危険があります。特にヘッダファイル内で書くと、そのヘッダを include した全てに影響するので厳禁。関数スコープ内に限定するか、using std::cout; のような using 宣言なら局所的で許容される流儀。
pair/tuple std::pair / std::tuple と構造化束縛 0 / 2

Q9 次のコードでbに入る値は?

std::pair<int, double> p{42, 3.14}; auto [a, b] = p; std::cout << b;
42
42, 3.14
3.14
コンパイルエラー(C++11 なので)
構造化束縛 auto [a, b] = p; は pair の first / second を順に a, b に取り出します。a = 42, b = 3.14 になり、出力は 3.14。C++17 以降で使える機能です。

Q10 空欄を埋めてください。3 つの値を組にして受け取るコード。

auto t = std:: (1, "Alice", 98.5);
答え: make_tuplestd::make_tuple(1, "Alice", 98.5); で tuple が作れます(型推論あり)。明示的に型を書くなら std::tuple<int, std::string, double> t{1, "Alice", 98.5};
iterator イテレータ 0 / 2

Q11 std::vector<int> v = {10, 20, 30}; のとき、v.end() が指すのは?

30(末尾要素)
10(先頭要素)
末尾要素の 1 つ先(そこには要素はない)
nullptr
end() は「末尾の要素の 1 つ先」。*v.end() は未定義動作。半開区間 [begin, end) の設計が STL 全体を統一的に扱えるカギ。

Q12 std::find が見つからなかったときの戻り値は?

-1
nullptr
std::string::npos
v.end()
イテレータを返す関数が「見つからなかった」ことを示すのに end() を返すのが STL の慣例。if (it != v.end()) でチェックします。nposstd::string::find 特有の戻り値で別物。

お疲れさまでした 🎉

0 / 12
次へ: STEP 3 へ進む