C++メモリ領域の分割
C++プログラム実行時のメモリは4つの領域に分割されます:
- コード領域: 関数のバイナリコードを格納
- グローバル領域: グローバル変数、静的変数、定数を格納
- スタック領域: 関数パラメータ、ローカル変数を格納(コンパイラ自動管理)
- ヒープ領域: プログラマが手動でメモリを割り当て/解放
プログラム実行前のメモリ状態
コンパイル後、実行前のメモリ状態:
// コード例: スタックとヒープの違い
#include <iostream>
using namespace std;
int* createStackVar() {
int stackValue = 42;
return &stackValue; // 危険: スタック変数のアドレス返却
}
int* createHeapVar() {
int* heapValue = new int(99);
return heapValue; // 安全: ヒープメモリのアドレス返却
}
int main() {
int* badPtr = createStackVar();
int* goodPtr = createHeapVar();
// cout << *badPtr << endl; // 未定義動作
cout << *goodPtr << endl; // 正常に動作
delete goodPtr; // ヒープメモリの解放
return 0;
}
参照(Reference)の仕組み
参照は変数の別名として機能し、以下の特徴を持ちます:
#include <iostream>
using namespace std;
void modifyViaRef(int& refVar) {
refVar *= 2; // 元の変数を直接変更
}
int main() {
int original = 10;
int& alias = original; // 参照の宣言
cout << "Original: " << original << endl;
alias = 20;
cout << "After alias modification: " << original << endl;
modifyViaRef(original);
cout << "After function call: " << original << endl;
return 0;
}
クラスとカプセル化
C++のクラスでは3つのアクセス制御を設定できます:
class Circle {
private:
double radius;
public:
void setRadius(double r) {
if (r > 0) radius = r; // データの有効性チェック
}
double getRadius() const {
return radius;
}
double calculateArea() const {
return 3.14159 * radius * radius;
}
};
コンストラクタとデストラクタ
class ResourceHolder {
private:
int* data;
public:
// コンストラクタ
ResourceHolder(int size) : data(new int[size]) {}
// デストラクタ
~ResourceHolder() {
delete[] data;
}
// コピーコンストラクタ
ResourceHolder(const ResourceHolder& other) {
data = new int[/*サイズ*/];
// ディープコピー処理
}
// 代入演算子オーバーロード
ResourceHolder& operator=(const ResourceHolder& other) {
if (this != &other) {
delete[] data;
data = new int[/*サイズ*/];
// コピー処理
}
return *this;
}
};
継承とポリモーフィズム
class Shape {
public:
virtual double area() const = 0; // 純粋仮想関数
virtual ~Shape() {}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
};
ファイル操作
#include <fstream>
#include <iostream>
using namespace std;
void writeToFile() {
ofstream outputFile("data.bin", ios::binary);
if (outputFile) {
int data[] = {1, 2, 3, 4, 5};
outputFile.write(reinterpret_cast<char*>(data), sizeof(data));
outputFile.close();
}
}
void readFromFile() {
ifstream inputFile("data.bin", ios::binary);
if (inputFile) {
int data[5];
inputFile.read(reinterpret_cast<char*>(data), sizeof(data));
inputFile.close();
}
}