C++のメモリ管理とオブジェクト指向機能の詳細解説

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();
    }
}

タグ: C++ メモリ管理 参照 クラス コンストラクタ

6月15日 20:12 投稿