知っておきたいC++の隠れた機能と実用的なテクニック集
C++には、コードをより短く、高速に書くための便利な機能やテクニックが数多く隠されています。特に競技プログラミングに参加する方にとっては、これらのテクニックを覚えておくことで実装時間を大幅に短縮できます。本記事では、実践で役立つC++のトリックを一つずつわかりやすく解説していきます。
%演算子を使わずに奇数・偶数を判定する
剰余演算子「%」を使わずに数値の偶奇を判定する方法です。考え方はシンプルで、数値と1のビットごとのAND(論理積)を取ります。結果が0でなければ奇数、0なら偶数です。
この仕組みの根拠は、すべての奇数は最下位ビット(LSb)が1になっているという点にあります。1とのAND演算を行うとLSb以外のビットがマスクされるため、簡単に判定できるのです。
if ((n & 1) != 0) {
// 奇数の場合
} else {
// 偶数の場合
}
シフト演算子による高速な乗算・除算
数値を2のn乗倍したい場合は、左へnビットシフトするだけです。同様に、2のn乗で割りたい場合は右へnビットシフトします。状況によっては通常の乗除算よりも高速に動作します。
x = 40; y = x << 2; // xに4を掛けるのと同じ、y = 160 cout << y; x = 40; y = x >> 2; // xを4で割るのと同じ、y = 10 cout << y;
第3の変数を使わずに2つの数値を交換する
+と-演算子を使ってもスワップは可能ですが、ビットXOR演算子を使う方法もあります。手計算で各ステップを追ってみると、その仕組みがよくわかります。
// xとyを交換 x ^= y; y ^= x; x ^= y;
strlen()を使わずに文字列を走査する
コードの制約上strlen()関数を使用できない場合は、自前のstrlen()を作成することになります。しかし、単に文字にアクセスするだけであれば、その必要はありません。位置iの文字が有効(非ゼロ)であるかを確認し、非ゼロなら走査を続け、ゼロならば停止すればよいのです。
for(int i = 0; s[i]; i++) {
cout << s[i];
}
push_back()より高速なemplace_back()
STLのvectorなどのコンテナに新しい要素を追加する際、通常はpush_back()を使いますが、emplace_back()も利用できます。こちらの方がはるかに高速です。別の場所にメモリを確保してからコピーするのではなく、コンテナ内で直接メモリを確保しながら要素を構築するためです。
組み込みのGCD関数
C++には最大公約数(GCD)を求める組み込み関数が用意されています。さまざまな場面で活用できます。構文は以下の通りです。
__gcd(x, y) // xとyの最大公約数を求める
配列サイズの上限について
main関数内で宣言できる配列の最大サイズは10^6程度です。一方、グローバル変数として宣言すれば、10^7までのサイズを確保できます。大きな配列が必要な場合は、グローバル宣言を検討しましょう。
log演算で最上位桁を求める
任意の数値の最上位桁(最も大きい位の桁)は、対数演算を使って計算できます。以下のロジックをご覧ください。
n = 4578; double k = log10(n); k = k – floor(k); int x = pow(10, k); // xが最上位桁になる
log演算で桁数を直接求める
ループを使わずに、log演算だけで桁数を直接計算できます。
n = 4578; int digit_count = floor(log10(n)) + 1;
2のべき乗かどうかを判定する
次のロジックを使えば、数値が2のべき乗であるかどうかを直接チェックできます。
x = 1024; bool check = x && (!(x & (x-1))); // trueであれば2のべき乗
all_of / any_of / none_of アルゴリズム
C++には、以下のような条件を簡潔にチェックできる組み込みアルゴリズムがあります。
all_of(left, left + n, isPositive()); // すべての要素が正かどうかを確認 any_of(left, left + n, isPositive()); // 少なくとも1つ正があるか確認 none_of(left, left + n, isPositive()); // 正の要素が1つもないことを確認
copy_n()で要素をコピーする
あるコンテナから別のコンテナへ要素をまとめてコピーするcopy_n()関数もあります。
int src[5] = {10, 20, 30, 40, 50};
int dest[5];
copy_n(src, 5, dest);
itoa()で連続した値の範囲を生成する
itoa()というアルゴリズムもあります。*firstに初期値を代入し、その後ポストインクリメント演算子で値を1ずつ増やしながら、連続的に増加する値の範囲を生成します。
int arr[5] = {0};
char str[5] = {0};
itoa(arr, arr+5, 15); // {15, 16, 17, 18, 19} を生成
itoa(str, str+5, 'A'); // {'A', 'B', 'C', 'D', 'E'} を生成
2進数リテラルで値を代入する
0b接頭辞を付けることで、その数値が2進数表記であることを明示できます。ビットフラグなどを扱う際に可読性が向上します。
int x = 0b1101; // xには13が格納される
条件演算子の代わりにキーワードを使用する
C++では、記号の論理演算子の代わりにキーワードを使用できます。例えば「&&」の代わりにキーワード「and」が使えます。
x = 10; if(x < 10 and x > 5) cout << \"True\" << endl; else cout << \"False\" << endl; // True が出力される
-
Windows 10の隠し機能8選:テクニカルプレビューで見つけた便利な新発見
Windows 10のテクニカルプレビュー(技術プレビュー版)を使い始めてしばらく経つと、あちこち触っていくうちに、まだ公式には紹介されていない「隠し機能」に思わず出会うことがあります。最終評価を下すにはまだ早い段階ですが、スタートメニューの復活やWindows 7とWindows 8の機能統合の流れを見る限り、こうした機能は今後さらに増えていく可能性が十分にありそうです。マイクロソフトがコンシューマー向けにまったく新しいOSをゼロから作り直さない限りは。まだ初期ビルドを試していない方のために、ここではエンタープライズユーザー向けに提供されている「Windows 10: Core Featur
-
macOS Mojaveの隠れた便利機能10選 – ベータ版で見つかった知られざる新機能
macOS Mojaveがついに登場しました。現在はまだベータ段階ですが、Appleは早期リリースを行い、ユーザーからのバグや不具合の報告を募っています。デスクトップスタック、ダークモード、ギャラリー表示など、注目の新機能についてはすでに耳にしたことがあるかもしれません。しかし、実はこれらはあくまで「表向き」の目玉機能にすぎません。その裏には、Mac体験を大きく変える隠れた機能が数多く眠っています。今回は、macOS Mojaveベータ版に搭載されている知られざる10の機能をご紹介します。macOS Mojaveベータ版の隠れた機能10選1. ダイナミックデスクトップダークモードを有効にすると