-
ヒープオーバーフローとスタックオーバーフローの違いと発生原因を解説
ヒープオーバーフローとはヒープは、動的に確保される変数を格納するためのメモリ領域で、プロセスのメモリ空間の一部です。C言語では malloc() や calloc() といった標準ライブラリ関数を使用することで、実行時に必要なサイズのメモリをヒープから取得できます。ヒープオーバーフローは、主に以下のようなケースで発生します。1. 巨大な動的メモリを一括で確保した場合int main() { float *ptr = (float *)malloc(sizeof(float) * 1000000); }一度に非常に大きなサイズのメモリを要求すると、システムが提供できるヒープ領域を超えてし
-
C++で可変数の引数(可変長引数)を扱う方法
プログラミングをしていると、引数の個数があらかじめ決まっていない関数、つまり呼び出しのたびに異なる数のパラメータを受け取れる関数が必要になる場面があります。C/C++ではこのような状況に対応する仕組みが用意されており、要件に応じて可変個の引数を受け取る関数を自由に定義できます。以下に、そのような関数の定義例を示します。 int func(int, ... ) { . . . } int main() { func(1, 2, 3); func(1, 2, 3, 4); } 注目すべきは、関数func()の最後の引数が省略記号(ピリオド3つの「...」)になってい
-
二次プロービング(Quadratic Probing)でハッシュテーブルを実装するC++プログラム
ハッシュテーブルは、キーと値のペアを格納するためのデータ構造です。ハッシュテーブルでは、ハッシュ関数を使って配列のインデックスを計算し、その位置へ要素を挿入または検索します。二次プロービング(Quadratic Probing)は、オープンアドレス法のハッシュテーブルにおける衝突解決手法の一つです。元のハッシュインデックスに対して、二次多項式から得られる間隔(1, 3, 5, 7, …と増加する値)を順次加算しながら探査を進め、空きスロットが見つかるまで処理を繰り返します。線形プロービングで問題となる一次クラスタリング(データが特定領域に集中する現象)を緩和できる点が特徴です。本記事では、二次
-
C++のコンストラクタから例外をスローする方法とデストラクタの挙動
概要C++では、コンストラクタの中からも例外をスロー(throw)することができます。オブジェクトの初期化中にエラーや不正な状態が検出された場合、コンストラクタ内で例外を投げることで、呼び出し元へエラーを適切に通知できます。本記事では、その基本的な仕組みを理解できるシンプルな例を紹介します。アルゴリズムクラスの説明と擬似コード:Begin クラスSample1を宣言する。 Sample1のコンストラクタを宣言する。 「Construct an Object of sample1」を出力する。 Sample1のデストラクタを宣言する
-
C++でオープンアドレッシング(線形プロービング)によるハッシュテーブルを自作する方法
ハッシュテーブルは、キーと値のペアを格納するためのデータ構造です。ハッシュテーブルはハッシュ関数を使用して配列のインデックスを計算し、その位置に要素を挿入または検索します。線形プロービング(Linear Probing)は、オープンアドレッシング方式のハッシュテーブルにおける衝突解決手法の一つです。この方式では、ハッシュテーブルの各セルには1つのキーと値のペアのみが格納されます。新しいキーが、すでに別のキーで占有されているセルにマッピングされると衝突が発生します。その場合、この手法はテーブル内で最も近い空きスロットを順次探索し、そこに新しいキーを挿入します。本記事では、C++で線形プロービング
-
C++の「++*p」「*p++」「*++p」の違いをわかりやすく解説
C++では、ポインタとインクリメント演算子を組み合わせた「*ptr++」「*++ptr」「++*ptr」は、一見よく似ていますが、動作はまったく異なります。本記事では、これら3つの式の違いを、演算子の優先順位の観点から具体例とともに解説します。 前置「++」と後置「++」の優先順位 まず、CおよびC++における演算子の優先順位を確認しておきましょう。 前置インクリメント「++」や前置デクリメント「--」は、間接参照演算子「*」よりも高い優先順位を持ちます。 後置インクリメント「++」や後置デクリメント「--」は、前置「++」および間接参照演算子「*」のどちらよりも高い優先順位を持ちます。
-
C++でAVL木(AVLツリー)を実装する方法:回転操作とサンプルコードを徹底解説
AVL木とは AVL木(AVL Tree)は、自己平衡型二分探索木(Self-balancing Binary Search Tree)の一種です。すべてのノードにおいて、左部分木と右部分木の高さの差が「1以下」に保たれるという性質を持っています。この平衡条件により、木が片側に偏って成長することを防ぎ、検索・挿入・削除といった操作を常に効率的(O(log n))に行うことができます。 木の回転(Tree Rotation)とは 木の回転とは、要素の順序(ソート順)を崩すことなく木の構造を変更する操作のことです。あるノードを一段上へ移動させ、別のノードを一段下へ移動させることで実現されます。 回
-
C++のインライン仮想関数の仕組みと動作を解説
C++における仮想関数(virtual function)は、基底クラスへのポインタや参照を使って、派生クラスの種類を意識することなく各クラスのメソッドを呼び出すための仕組みです。仮想関数はコンパイル時ではなく、実行時(ランタイム)に解決されます。仮想関数とインライン関数の役割仮想関数の主な目的は、実行時ポリモーフィズム(動的多態性)を実現することです。一方、インライン関数はコードの実行効率を高めるために使われます。インライン関数が呼び出されると、コンパイラはその呼び出し箇所に関数のコードを直接展開します。これにより、関数呼び出しのオーバーヘッドが削減されます。仮想関数がインライン化できる条件
-
C++の純粋仮想デストラクタとは?仕組みと実装例を解説
純粋仮想デストラクタとは C++では、デストラクタを純粋仮想関数として宣言することが可能です。ただし、クラスに純粋仮想デストラクタが含まれる場合は、必ずその関数本体(実装)を提供しなければなりません。実装を省略すると、リンク時にエラーが発生します。 これは、オブジェクトが破棄される際に、派生クラスのデストラクタから基底クラスのデストラクタが必ず呼び出されるためです。純粋仮想として宣言していても、この呼び出しに応えるための実体が必要になります。 サンプルコード #include <iostream> using namespace std; class B { public:
-
【C++】仮想関数と純粋仮想関数の違いを徹底解説!宣言方法と使い分けのポイント
C++のオブジェクト指向プログラミングにおいて、ポリモーフィズム(多態性)を実現するために欠かせないのが「仮想関数(Virtual Function)」です。さらに、その特殊な形として「純粋仮想関数(Pure Virtual Function)」が存在します。本記事では、この2つの違いを比較表とサンプルコードを使いながら、初心者にもわかりやすく解説します。仮想関数と純粋仮想関数の違い一覧仮想関数(Virtual Function)純粋仮想関数(Pure Virtual Function)クラス内に実装(定義)を持つ。実装(定義)を持たず、「= 0」として宣言される。宣言方法:virtual 関
-
C++のコンストラクター内で仮想関数を呼び出すとどうなるか?危険性と理由を解説
C++では、コンストラクターやデストラクター内から仮想関数を呼び出すことは危険であり、可能な限り避けるべきとされています。 その理由は、コンストラクター内で呼び出した仮想関数が派生クラスのものではなく、常に基底クラス(Baseクラス)のものとして実行されるためです。直感的には「派生クラスでオーバーライドした関数が呼ばれる」と思いがちですが、実際の動作は異なります。 なぜ基底クラス側の仮想関数が呼ばれるのか? C++では、スーパークラス(基底クラス)が派生クラスより先に構築されるという規則があります。つまり、派生クラスのオブジェクトを生成する場合、処理順序は次のようになります。 まず基底クラ
-
C++の仮想関数にデフォルト引数を設定できますか?
はい、C++の仮想関数にもデフォルト引数(デフォルトパラメータ)を設定することができます。ただし、その動作には直感に反する重要なポイントがあるため、仕組みを正しく理解しておくことが大切です。サンプルコード#include<iostream> using namespace std; class B { public: virtual void s(int a = 0) { cout << In Base \n; } }; class D : public B { public: virtual void s(int a) {
-
C++で文字列照合のためのBitapアルゴリズムを実装する方法
これは、文字列照合のためのBitapアルゴリズムを実装したC++プログラムの解説です。Bitapアルゴリズムは、指定されたテキストの中に、与えられたパターンと「ほぼ一致」する部分文字列が含まれているかどうかを判定します。ここでの「近似一致」はレーベンシュタイン距離(編集距離)に基づいて定義されており、部分文字列とパターンとの距離が許容値k以内であれば、両者は一致しているとみなされます。 このアルゴリズムは、まずパターンの各要素に対応する1ビットからなるビットマスクの集合を事前に計算します。これにより、処理の大部分を極めて高速なビット演算だけで実行できる点が大きな特徴です。Bitapアルゴリズ
-
C++で実装する短いテキスト向け文字列検索アルゴリズムの解説
このC++プログラムでは、入力としてテキスト(元の文字列)とパターン(検索したい文字列)を受け取ります。そして、テキストの中からパターンを検索し、見つかったすべての出現位置と合計マッチ数を出力します。 本記事では、単純な二重ループ(総当たり方式)による文字列検索アルゴリズムの考え方と、実際に動作するサンプルコード、実行結果までをわかりやすく解説します。 アルゴリズムの流れ 開始 文字列とパターンを入力として受け取る。 元の文字列用とパターン用の配列を宣言する。 それぞれの長さを len_ori と len_dupli に格納する。 ループを使ってパターンが一致する位置を探す
-
2つのスタックを使ってキューを実装するC++プログラム
スタック(Stack)とは スタックはLIFO(Last In First Out:後入れ先出し)方式のデータ構造で、挿入と削除が同じ端(トップ)から行われます。最後に入れた要素が最初に取り出されます。 スタックの基本操作は次のとおりです。 push(int data) − トップに要素を挿入する int pop() − トップから要素を削除して返す キュー(Queue)とは キューはFIFO(First In First Out:先入れ先出し)方式のデータ構造で、挿入は一方の端(リア)から、削除はもう一方の端(フロント)から行われます。最初に入れた要素が最初に取り出されます。 キューの
-
C++における cout << endl と cout << "\n" の違いを徹底解説
はじめに 本記事では、C++における cout << endl と cout << "\n" の違いについて詳しく解説します。多くの場面では改行に "\n" を使用し、endl の使用を避けるべきである理由を、パフォーマンスの観点から紹介します。 std::endl を避けるべき理由 コンソールやファイルに文字列を出力する際、なぜ std::endl を避けるべきなのでしょうか。std::endl は現在の行の末尾で改行を行うために使われます。数行程度の入出力処理であれば特に問題はありませんが、大量の入出力タスクを扱う場合には、パ
-
C++で2つのキューを使ってスタックを実装する方法(サンプルコード付き)
スタック(Stack)とは スタックはLIFO(Last In First Out:後入れ先出し)方式で動作するデータ構造です。要素の挿入と削除がすべて同じ端(トップ)から行われ、最後に入力した要素が最初に取り出されます。 スタックの主な操作は以下のとおりです。 push(int data) − トップに要素を挿入する int pop() − トップから要素を削除(取り出し)する キュー(Queue)とは キューはFIFO(First In First Out:先入れ先出し)方式で動作するデータ構造です。挿入は一方の端(リア/末尾)から行い、削除はもう一方の端(フロント/先頭)から行いま
-
C++でデキュー(両端キュー)を実装する方法|アルゴリズムとサンプルコード解説
デキュー(両端キュー)とは デキュー(Dequeue/Double Ended Queue:両端キュー)は、通常のキューを一般化したデータ構造で、先頭と末尾の両端から要素の挿入・削除が可能な点が最大の特徴です。通常のキューでは「末尾への挿入」と「先頭からの削除」しか行えませんが、デキューではどちらの端からでも操作できます。 デキューの基本的な操作は以下の4つです。 insert_at_beg() … デキューの先頭に要素を挿入する insert_at_end() … デキューの末尾に要素を挿入する delete_fr_beg() … デキューの先頭から要素を削除する delete_fr_re
-
C++のfread()関数の使い方を徹底解説!パラメータとサンプルコード付き
fread()関数とはC/C++の標準ライブラリ関数であるsize_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)は、指定されたストリームからデータを読み込み、ptrが指す配列に格納します。テキストファイルだけでなく、構造体や配列などのバイナリデータを読み込む際に特に便利な関数です。fread()関数の宣言は以下の通りです。size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)パラメータの詳細fread()関数が受け取る各パラメータの説明は以下の表の
-
【C++】配列でキュー(Queue)を実装する方法とサンプルコード
キュー(Queue)とは キューはFIFO(First In First Out:先入れ先出し)方式のデータ構造です。要素の挿入は一端(後端=rear)から行い、削除はもう一方の端(前端=front)から行います。そのため、最初に入った要素が最初に取り出されます。 キューの基本操作 EnQueue(int data):後端(rear)に要素を挿入する DeQueue():前端(front)から要素を削除する この記事では、配列を使ってC++でキューを実装する方法とサンプルコードを紹介します。 アルゴリズム Enqueue():キューへの挿入キューが満杯の場合は「Overflow」と表示