プログラミング言語には、低レベル言語や高レベル言語などの分類があり、メモリ管理や書き方・用途・できること・できないことに違いがあります。
以下で、C、C++、Java、C#、JavaScript、Python、Dartなどの主要な言語を比較して解説します。
malloc
や free
を使用してメモリを明示的に割り当て・解放する。ポインタ操作による直接的なメモリ操作が可能。例:
#include <stdlib.h> // mallocとfreeのために必要なヘッダーをインクルード
int main() {
int *p = malloc(sizeof(int));// メモリを動的に確保する(int型1つ分のサイズを確保)
*p = 10;// 確保したメモリに10を代入
free(p);// 確保したメモリを解放する
return 0;// 正常終了を示すために0を返す
}
new
と delete
による手動メモリ管理に加え、スマートポインタなどの自動メモリ管理機能もある。例:
#include <iostream>
int main() {
int* p = new int(10);// ヒープ領域にint型のメモリを確保し、値10を初期化
delete p;// 確保したメモリを解放
return 0;// 正常終了を示すために0を返す
}
例:
public class Main {
public static void main(String[] args) {
// Integerクラスのオブジェクトを新規に生成しています。
// ここで "new Integer(10)" は、ヒープ領域に数値10を持つIntegerオブジェクトを作成します。
Integer num = new Integer(10);
// しかし、Javaでは、オートボクシングという機能により
// "new Integer(10)" の代わりに、単に "Integer num = 10;" と書けます。
// これは、基本データ型の値(int型の10)が自動的にIntegerオブジェクトに変換されるためです。
// そのため、"new Integer(10)" を使うケースは今ではほとんどなく、非推奨となっています。
// メモリ管理:
// Javaにはガベージコレクタ(GC)があるため、C++のように手動でdeleteを行う必要はありません。
// num変数がスコープを抜けた時点や不要になった時点で、GCがこのオブジェクトを検出し、
// メモリを自動で解放してくれます。
}
}
例:
using System;
class Program {
static void Main() {
// ここでは、int型の変数numを宣言し、値10を代入しています。
int num = 10;
// intはC#の基本型(値型)であり、スタックメモリに格納されます。
// ヒープではなく、スタックに格納されるため、特にメモリ管理の心配はありません。
// num変数がスコープを抜ける(このMainメソッドが終了する)と、スタックメモリから自動的に解放されます。
// C#では、メモリ管理は基本的にガベージコレクタ(GC)が自動で行います。
// 基本型(int, floatなど)はスタックに置かれますが、オブジェクト型(クラスなどのインスタンス)は
// ヒープに置かれ、GCが不要になったタイミングで自動解放します。
}
}
例:
using System;
using System.Collections.Generic;
class Task {
public string Name { get; set; }
public bool IsCompleted { get; private set; }
public Task(string name) {
Name = name;
IsCompleted = false;
}
public void Complete() {
IsCompleted = true;
Console.WriteLine($"タスク '{Name}' が完了しました。");
}
public override string ToString() {
return $"{Name} - {(IsCompleted ? "完了" : "未完了")}";
}
}
class Program {
static void Main() {
List<Task> tasks = new List<Task>();
string command;
Console.WriteLine("タスク管理アプリにようこそ!");
do {
Console.WriteLine("\nコマンドを入力してください:");
Console.WriteLine("1: タスクを追加する");
Console.WriteLine("2: タスクを完了する");
Console.WriteLine("3: タスクを表示する");
Console.WriteLine("4: 終了する");
command = Console.ReadLine();
switch (command) {
case "1":
Console.Write("追加するタスクの名前を入力してください: ");
string taskName = Console.ReadLine();
tasks.Add(new Task(taskName));
Console.WriteLine($"タスク '{taskName}' を追加しました。");
break;
case "2":
Console.Write("完了するタスクのインデックスを入力してください (0から始まる番号): ");
if (int.TryParse(Console.ReadLine(), out int index) && index >= 0 && index < tasks.Count) {
tasks[index].Complete();
} else {
Console.WriteLine("無効なインデックスです。");
}
break;
case "3":
Console.WriteLine("\nタスクリスト:");
for (int i = 0; i < tasks.Count; i++) {
Console.WriteLine($"{i}: {tasks[i]}");
}
break;
case "4":
Console.WriteLine("アプリを終了します。");
break;
default:
Console.WriteLine("無効なコマンドです。");
break;
}
} while (command != "4");
}
}
[C#実行例](/Unity_Lesson/1_ElementaryKnowledge/CS%E5%AE%9F%E8%A1%8C%E4%BE%8B.html)
ScoreManager,cs
using UnityEngine;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour
{
public static ScoreManager Instance; // シングルトンインスタンス
public int Score { get; private set; } = 0; // スコア
public Text scoreText; // UIテキストオブジェクト
private void Awake()
{
// シングルトンの実装
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject); // シーンをまたいでオブジェクトを保持
}
else
{
Destroy(gameObject); // 既に存在する場合は削除
}
}
// スコアを加算するメソッド
public void AddScore(int points)
{
Score += points;
UpdateScoreText();
}
// スコアテキストを更新するメソッド
private void UpdateScoreText()
{
scoreText.text = "Score: " + Score;
}
}
PlayerController.cs
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private void Update()
{
// スペースキーを押したときにスコアを加算
if (Input.GetKeyDown(KeyCode.Space))
{
ScoreManager.Instance.AddScore(10); // スコアを10加算
}
}
}
例:
let num = 10;
console.log(num);
例:
function createObject() {
// スタックにローカル変数が格納される
const localConstant = "I am constant"; // スタックに格納され、再代入不可
let localVariable = 10; // スタックに格納され、再代入可能
// ヒープにオブジェクトを作成
const myObject = {
message: "I am an object",
value: 42
}; // `const` なので、プロパティの変更は可能だが、再代入は不可
console.log(localConstant); // スタックから値を取得
console.log(localVariable); // スタックから値を取得
console.log(myObject.message); // ヒープからオブジェクトのプロパティを取得
// `let`で宣言した変数の再代入
localVariable += 5;
console.log("Updated localVariable:", localVariable); // 15 が出力される
// オブジェクトのプロパティを更新
myObject.value += 10;
console.log("Updated myObject.value:", myObject.value); // 52 が出力される
// myObjectの参照を返す
return myObject;
}
// createObjectが呼ばれ、ローカル変数がスタックに追加される
const obj = createObject();
console.log(obj.value); // ヒープに格納されたオブジェクトのプロパティを参照(52 が出力される)
htmlと一緒に使った例:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>タスク管理アプリ</title>
<style>
body { font-family: Arial, sans-serif; }
ul { list-style-type: none; padding: 0; }
li { padding: 8px; margin: 4px 0; background-color: #f0f0f0; }
button { margin-left: 10px; }
</style>
</head>
<body>
<h1>タスク管理アプリ</h1>
<input type="text" id="taskInput" placeholder="新しいタスクを追加">
<button id="addTaskBtn">タスクを追加</button>
<h2>タスクリスト</h2>
<ul id="taskList"></ul>
<script>
// タスクリストを保持する配列
let tasks = [];
// タスクを追加する関数
function addTask() {
const input = document.getElementById('taskInput');
const task = input.value.trim();//文字列の前後にある空白(スペース、タブ、改行など)を取り除く
if (task) {
// タスクを配列に追加
tasks.push(task);
input.value = ''; // 入力フィールドをクリア
renderTasks(); // タスクリストを再描画
} else {
alert('タスクを入力してください。');
}
}
// タスクリストを描画する関数
function renderTasks() {
const taskList = document.getElementById('taskList');
taskList.innerHTML = ''; // 既存のリストをクリア
// タスクをリストに追加
tasks.forEach((task, index) => {
const li = document.createElement('li');
li.textContent = task;
// 削除ボタンを作成
const deleteBtn = document.createElement('button');
deleteBtn.textContent = '削除';
deleteBtn.onclick = () => deleteTask(index);
li.appendChild(deleteBtn);
taskList.appendChild(li);
});
}
// タスクを削除する関数
function deleteTask(index) {
tasks.splice(index, 1); // 配列からタスクを削除
renderTasks(); // タスクリストを再描画
}
// ボタンのクリックイベントを設定
document.getElementById('addTaskBtn').addEventListener('click', addTask);
</script>
</body>
</html>
num = 10
print(num)
例:
class Counter:
def __init__(self):
self._count = 0 # 初期カウント値を0に設定
def increment(self):
"""カウントを増加させるメソッド"""
self._count += 1
print(f"Current count: {self._count}")
def reset(self):
"""カウントをリセットするメソッド"""
self._count = 0
print("Counter reset to 0.")
def get_count(self):
"""現在のカウント値を取得するメソッド"""
return self._count
def main():
counter = Counter() # Counterクラスのインスタンスを作成
while True:
action = input("Enter 'i' to increment, 'r' to reset, or 'q' to quit: ").lower()
if action == 'i':
counter.increment() # カウントを増加
elif action == 'r':
counter.reset() # カウントをリセット
elif action == 'q':
print(f"Final count: {counter.get_count()}") # 最終カウントを表示
break # ループを終了
else:
print("Invalid input. Please enter 'i', 'r', or 'q'.")
if __name__ == "__main__":
main()
例:
class MyObject:
def __init__(self, message, value):
# ヒープに格納されるオブジェクトの属性を初期化
self.message = message
self.value = value
def display_message(self):
# ヒープからオブジェクトのメッセージを取得して表示
print(f"Message: {self.message}")
def update_value(self, new_value):
# オブジェクトの値を更新
self.value = new_value
print(f"Value updated to: {self.value}")
def create_object():
# スタックにローカル変数が格納される
local_variable = "I am local" # スタックに格納される
print(local_variable) # スタックから値を取得
# ヒープにオブジェクトを作成
my_object = MyObject("I am an object", 42) # ヒープに格納される
my_object.display_message() # ヒープからオブジェクトのプロパティを取得
# my_objectの参照を返す
return my_object
# メイン処理
if __name__ == "__main__":
obj = create_object() # create_objectが呼ばれ、ローカル変数がスタックに追加される
print(f"Initial value: {obj.value}") # ヒープに格納されたオブジェクトのプロパティを参照
obj.update_value(100) # オブジェクトの値を更新
void main() {
int num = 10;
print(num);
}
例:
class Counter {
int _count = 0; // 初期値を0に設定
// 現在のカウント値を取得するメソッド
int get count => _count;
// カウントを増加させるメソッド
void increment() {
_count++;
print("Current count is: $_count");
}
// カウントをリセットするメソッド
void reset() {
_count = 0;
print("Counter reset. Current count is: $_count");
}
}
void main() {
Counter counter = Counter(); // Counterクラスのインスタンスを作成
counter.increment(); // カウントを1増加
counter.increment(); // カウントをさらに1増加
print("Final count after increments: ${counter.count}"); // 現在のカウントを出力
counter.reset(); // カウントをリセット
}
例:
class MyObject {
String _message;
int _value;
MyObject(this._message, this._value);
// メッセージの取得
String get message => _message;
// 値の取得と更新
int get value => _value;
set value(int newValue) {
_value = newValue;
print("MyObject value updated to: $_value");
}
// メッセージを表示するメソッド
void displayMessage() {
print("Message: $_message");
}
}
void createObject() {
// 定数として再代入不可のローカル変数
final String localConstant = "I am a constant";
// 再代入可能なローカル変数
String localVariable = "I am a local variable";
// オブジェクトを作成(プロパティは変更可能)
final MyObject myObject = MyObject("I am an object", 42);
print(localConstant); // 定数を出力
print(localVariable); // ローカル変数を出力
myObject.displayMessage(); // オブジェクトのメッセージを出力
// 再代入可能なローカル変数の更新
localVariable = "Updated local variable";
print(localVariable); // 更新後のローカル変数
// プロパティの更新と出力
myObject.value = 100;
print("Current myObject.value: ${myObject.value}");
}
void main() {
createObject();
}
言語 | レベル | メモリ管理 | 書き方の特徴 | できること | できないこと |
---|---|---|---|---|---|
C | 低-中 | 手動管理 | ハードウェア寄り、ポインタ使用 | 組み込み、OS、デバイスドライバ | 高レベルの抽象化、手動管理の手間が大きい |
C++ | 中間 | 手動&自動(スマートポインタ) | オブジェクト指向、テンプレート | ゲーム開発、アプリ、ハードウェア制御 | 自動GCなし、メモリリークに注意が必要 |
Java | 高 | 自動(GC) | オブジェクト指向、クラスベース | エンタープライズ、Web、Android | システム操作の低レベル制御が困難 |
C# | 高 | 自動(GC) | .NET統合、シンプル | デスクトップ、Web、ゲーム(Unity) | Windows向けが強い |
JavaScript | 高 | 自動(GC) | Web向け、スクリプト言語 | Webアプリ、サーバーサイド(Node.js) | 低レベル操作が困難 |
Python | 高 | 自動(GC) | インデントベース、シンプル | データサイエンス、AI、Web | パフォーマンスが低い、低レベル操作が苦手 |
Dart | 高 | 自動(GC) | モダン、Flutterで使用 | クロスプラットフォームのアプリ開発 | 低レベル操作が困難、Flutter以外での普及がまだ少ない |