ã¢ãã³ç¬¬1ç« ïŒãC++11ãã¹ããŒããã€ã³ã¿ãšRAIIïŒæææš©èšèšãšã¡ã¢ãªå®å
šæ§ïŒ
std::unique_ptr ãš std::shared_ptr ã«ãããªãœãŒã¹å®å
šèªå管ç
第4ç« ã§å€æ
æ§ãæã«å
¥ãããã®ã®ãæµã®çæã»ç Žæ£ã«ã¯çã® new / delete ã䜿ã£ãŠããŸãããæ¬ç« ã§ã¯ãçãã€ã³ã¿ã®è§£æŸæŒãããã³ã°ãªã³ã°ãã€ã³ã¿ãèšèšã¬ãã«ã§æ²æ»
ããC++ã®éåå¡ãã¹ããŒããã€ã³ã¿ïŒunique_ptr, shared_ptr, weak_ptrïŒããšãæææš©ïŒOwnershipïŒãã®èŠåŸãäœåŸããŸãã
5.1 çãã€ã³ã¿ã®æ²åïŒè§£æŸæŒãã»äºéè§£æŸã»ãã³ã°ãªã³ã°ãã€ã³ã¿
ãmalloc/free ãæäœæ¥ã§è¿œè·¡ããŠããCèšèªãããè±åŽããã¯ãããåæC++ã§ããnew ãš delete ã®å¯Ÿå¿ãæåã§æ°ããèŠè¡ããç¶ããŠããŸããããªãçãã€ã³ã¿ã®æå管çã¯ç Žç¶»ããã®ãããã®ç©ççã¡ã«ããºã ãè§£åããŸãã
ð§ ãã³ã®ã³å
茩
ãã³å
çïŒç¬¬4ç« ã§æµã®ããªã¢ãŒãã£ãºã ãããããªåããŸããïŒã§ããæµãåãããšãã« `delete enemy; enemies.erase(it);` ã£ãŠæ¯åæã§æžãã®ãã¡ãã£ãšç·åŒµããŸããâŠâŠã
ð»ââïž ã·ãã¯ãå
ç
ãã®ç·åŒµæãããæ£ãããšã³ãžãã¢ã®çŽæããããã³ã®ã³ïŒãŸãã«çŸå Žã§èµ·ããé倧ã¯ã©ãã·ã¥ã®8å²ã¯ããã®ãæåã® deleteãããçãŸããŠããïŒããéäžã§ return ããããerase ã ãã㊠delete ãå¿ãããã©ããªãïŒ
ð§ ãã³ã®ã³å
茩
ãã£âŠâŠããŒãã«æµã®ã¡ã¢ãªãæ®ã£ããŸãŸãäºåºŠãšè§£æŸã§ããªããªããã¡ã¢ãªãªãŒã¯ãã§ããïŒéã«ãdelete ããåŸã®ãã€ã³ã¿ãå¥ã®å Žæããè§Šã£ã¡ãã£ããâŠâŠïŒ
ð»ââïž ã·ãã¯ãå
ç
ãããããããã³ã°ãªã³ã°ãã€ã³ã¿ïŒå¢å Žåç
§ïŒãããïŒãã§ã«æ»ãã ã¡ã¢ãªçªå°ãèªã¿æžãããŠããŸããåè§ŠããªãOSãã匷å¶çµäºïŒã»ã°ãã©ïŒãé£ãããã ãå®å¿ãããã¢ãã³C++ã«ã¯ãnew ã delete ã1æåãæžããªãã究極ã®èŠåŸãããã®ããïŒ
5.2 std::unique_ptr ãšæææš©ã®ç§»åïŒã ãŒãã»ãã³ãã£ã¯ã¹ïŒ
ãªã unique_ptr ã¯ã³ããŒã§ããªãã®ãïŒãå¯äžã®ææè
ïŒSingle OwnershipïŒããšããææ³ãšãã¢ã€ãã ã«ãã»ã«ãæµããã¹ããŒãžãžããããŠãã¬ã€ã€ãŒãžæž¡ããããæææš©ã®ç§»åïŒstd::moveïŒããåŠã³ãŸãã
### â ãªã unique_ptr ã¯ã³ããŒã§ããªãã®ãïŒ
`std::unique_ptr` ã®æå€§ã®ç¹åŸŽã¯ã**ã³ããŒã³ã³ã¹ãã©ã¯ã¿ãšã³ããŒä»£å
¥æŒç®åãåé€ïŒ= deleteïŒãããŠãã**ç¹ã§ãã
```cpp
std::unique_ptr<Enemy> p1 = std::make_unique<NormalEnemy>(10, 2);
std::unique_ptr<Enemy> p2 = p1; // ã³ã³ãã€ã«ãšã©ãŒïŒã³ããŒã¯çµ¶å¯Ÿã«çŠæ¢ïŒ
```
ãããããèš±å¯ãããŠãããã`p1` ãš `p2` ãåãããŒãå®äœãæããŠããŸããŸãããããšã¹ã³ãŒããæããéã**2å delete** ãããŠã¯ã©ãã·ã¥ïŒäºéè§£æŸïŒããŠããŸããŸãã
### â æææš©ã®ç§»åïŒMove SemanticsïŒ
ã³ããŒã¯çŠæ¢ã§ããã**ãæã¡äž»ã®å€æŽïŒè²æž¡ïŒã**ã¯èš±å¯ãããŠããŸããããã `std::move()` ã§ãã
```cpp
std::unique_ptr<Enemy> p2 = std::move(p1);
// p1 㯠nullptr ã«ãªããp2 ãæ°ããªå¯äžã®ææè
ãšãªãïŒ
```
ã²ãŒã å
ã§ã¯ãæµãåããç¬éã«çæãããã¢ã€ãã ã«ãã»ã«ãïŒ
1. æµã®å
éšã§ `std::make_unique<Item>()` ããã
2. ã¹ããŒãžã® `m_items` ãªã¹ããž `std::move()` ããã
3. ãã¬ã€ã€ãŒãè§Šããç¬éããã¬ã€ã€ãŒãžåŒãæž¡ããã
ãšãã**ãæææš©ã®ãªã¬ãŒã**ãæ¥µããŠå®å
šã«è¡ãããŸãã
5.3 std::shared_ptr ãš std::weak_ptr ã«ããå
±æãªãœãŒã¹ç®¡ç
ãã©ãããŠãè€æ°ã®ãªããžã§ã¯ãããåãå®äœãåæã«ææããããå Žåã¯ã©ãããã®ãïŒåç
§ã«ãŠã³ãæ¹åŒã® shared_ptr ãšã埪ç°åç
§ã«ããæ°žä¹
ã¡ã¢ãªãªãŒã¯ãé²ã weak_ptr ã解説ããŸãã
ð§ ãã³ã®ã³å
茩
å
çãunique_ptr ã®åãã¯ããããŸããïŒã§ããä»åç»å Žãããèªæ©ãè·è¡ããããããããŒã³ïŒåæ©ïŒãã¯ãèªæ©ïŒPlayerïŒãæŽæ°ãããããã¹ããŒãžïŒGameïŒãåœããå€å®ã§åç
§ãããã§ããããããæã¯ã©ããããã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
è¯ã質åããïŒè€æ°ã®æã¡äž»ã§1ã€ã®å®äœãã·ã§ã¢ãããæããããstd::shared_ptrãã®åºçªããïŒå
éšã«ãåç
§ã«ãŠã³ã¿ïŒuse_countïŒããæã¡ãææè
ã1人å¢ãããã³ã« +1ãææŸããã³ã« -1 ãããæåŸã®1äººãææŸããç¬éã«èªåç Žæ£ãããïŒ
ð§ ãã³ã®ã³å
茩
䟿å©ã§ããïŒãããå
šéš shared_ptr ã«ãã¡ããã°ããããããªãã§ããïŒ
ð»ââïž ã·ãã¯ãå
ç
ãã«è
ãïŒãããããåå¿è
ãé¥ãã埪ç°åç
§ã®æ»ã®çœ ãããïŒAãBãæã¡ãBãAãæã€ãšãã«ãŠã³ã¿ãæ°žé ã«0ã«ãªãããã¡ã¢ãªãæ°žä¹
ã«è§£æŸãããªããªãïŒã ãããããç£èŠããã ããªã std::weak_ptrãã§åŒ±ãç¹ãã®ããïŒ
### â 管çãããã¯ïŒControl BlockïŒãšåç
§ã«ãŠã³ã
`std::shared_ptr` ãäœæãããšãããŒãé åã«**ãå®äœã**ãš**ã管çãããã¯ã**ã®2ã€ã確ä¿ãããŸãã
- **use_count**: çŸåšã®å®äœææè
æ°ïŒããã 0 ã«ãªããšå®äœã `delete` ãããïŒ
- **weak_count**: ç£èŠäžã® `std::weak_ptr` ã®æ°ïŒããã 0 ã«ãªããšç®¡çãããã¯èªäœãç Žæ£ãããïŒ
```cpp
// ãã¬ã€ã€ãŒåšå²ã®è·è¡ããããããŒã³ãçæ
std::shared_ptr<BitDrone> drone = std::make_shared<BitDrone>(0.0f);
// use_count: 1
m_player.addDrone(drone);
// ãã¬ã€ã€ãŒå
éšã® vector ã«ã³ããŒä¿åããã â use_count: 2
// ã²ãŒã ã«ãŒãã§ drone 倿°ã®ã¹ã³ãŒããçµãã£ãŠãã
// m_player ãæææš©ãæã£ãŠããã®ã§ use_count: 1 ãšãªãå®äœã¯çãç¶ããïŒ
```
### â 埪ç°åç
§ïŒæ»ã®ããã¯ïŒãš weak_ptr ã®å¿
ç¶æ§
ããããããæ©ãã芪ã®ããã¬ã€ã€ãŒããžã®ãã€ã³ã¿ã `shared_ptr<Player>` ã§æã£ãŠããŸããšïŒ
- ãã¬ã€ã€ãŒã¯ãããæ©ãææïŒuse_count = 1ïŒ
- ãããæ©ã¯ãã¬ã€ã€ãŒãææïŒuse_count = 1ïŒ
äºãã«åç
§ãåã£ãŠãããããã²ãŒã ãçµãã£ãŠãã©ã¡ãã® `use_count` ã 0 ã«ãªããã**æ°žé ã«ãã¹ãã©ã¯ã¿ãåŒã°ããªãæ»ã®ã¡ã¢ãªãªãŒã¯**ãçºçããŸãã
ãããé²ããããéåç
§ãç£èŠåŽã«ã¯ `std::weak_ptr<Player>` ã䜿ããŸãã
`weak_ptr` ã¯åç
§ã«ãŠã³ããå¢ãããã䜿ããšãã ã `drone->lock()` ããŠäžæç㪠`shared_ptr` ãåãåºããŸãã
5.4 æå delete ã1è¡ãæžããªã宿ãããã²ãŒã ã«ãŒã
第5ç« ã®å®æ©ã³ãŒãã§ã¯ãã³ã³ã¹ãã©ã¯ã¿ãã²ãŒã ã«ãŒãããã¹ãã©ã¯ã¿ã®ã©ãã«ã delete ãçŸããŸãããerase ããã ãã§äžèº«ãèªåç Žæ£ãããçŸããã宿ããŠãã ããã
ð Game.h
#pragma once
#include <vector>
#include <memory>
#include <string>
#include "Common.h"
#include "Player.h"
#include "Enemy.h"
#include "Item.h"
#include "Bullet.h"
#include "Particle.h"
class Game {
private:
// ãã¢ãã³C++ã®æ¥µèŽãçãã€ã³ã¿ã¯ãŒãïŒãã¹ãŠã¹ããŒããã€ã³ã¿ã§ç®¡ç
std::vector<std::unique_ptr<Enemy>> m_enemies; // æµã®åç¬ææ
std::vector<std::unique_ptr<Item>> m_items; // ããããã¢ã€ãã ã®åç¬ææ
std::vector<Bullet> m_bullets; // 匟䞞
std::vector<Particle> m_particles;// ç«è±ç²å
Player m_player; // èªæ©
int m_enemyDir;
int m_enemyMoveTimer;
int m_ufoTimer;
int m_score;
bool m_gameOver;
bool m_gameClear;
public:
Game();
// ãã¹ãã©ã¯ã¿ã«æå delete ã«ãŒãã¯1è¡ãäžèŠïŒ
// vectorç Žæ£ã«äŒŽããå unique_ptr ãæŽŸçã¯ã©ã¹ã®ä»®æ³ãã¹ãã©ã¯ã¿ãèªåèµ·å
~Game() = default;
void init();
void processInput();
void update();
void render();
};
ð Player.h
#pragma once
#include <vector>
#include <memory>
#include <string>
#include "Common.h"
#include "Bullet.h"
#include "BitDrone.h"
class Player {
private:
int m_x;
int m_y;
bool m_hasTripleShot;
// è·è¡ããããããŒã³ãå
±æææïŒshared_ptrïŒ
std::vector<std::shared_ptr<BitDrone>> m_drones;
public:
Player(int startX, int startY);
~Player() = default;
void moveLeft();
void moveRight();
void update();
void draw(std::vector<std::string>& buffer) const;
// 匟ãçºå°ïŒ3WAYããããé£åïŒ
void shoot(std::vector<Bullet>& bullets) const;
void enableTripleShot() { m_hasTripleShot = true; }
void addDrone(std::shared_ptr<BitDrone> drone);
int getDroneCount() const { return static_cast<int>(m_drones.size()); }
};
ð Item.h
#pragma once
#include <vector>
#include <string>
#include "Common.h"
enum class ItemType {
Power, // 3WAYã¬ãŒã¶ãŒå ('P')
Bit // æŽè·ããããããŒã³è¿œå ('B')
};
class Item {
private:
float m_x;
float m_y;
ItemType m_type;
bool m_active;
public:
Item(float x, float y, ItemType type);
~Item() = default;
void update();
void draw(std::vector<std::string>& buffer) const;
float getX() const { return m_x; }
float getY() const { return m_y; }
ItemType getType() const { return m_type; }
bool isActive() const { return m_active; }
void deactivate() { m_active = false; }
};
ð¡ ãã®ã»ã¯ã·ã§ã³ã®éèŠãã€ã³ã
- 9å²ã®èšèšã¯ std::unique_ptr ã§å®çµãã: ãªãŒããŒããããŒãã§çã®ãã€ã³ã¿ãšåäžé床ãå¯äžã®æææš©ãæç¢ºã«ããå®æãª shared_ptr ä¹±çšãé¿ããã®ãã¢ãã³C++ã®éåã§ãã
- std::make_unique / std::make_shared ã䜿ã: new ãæžããã«ãã«ããŒé¢æ°ã䜿ãããšã§ãäŸå€çºçæã®ã¡ã¢ãªãªãŒã¯ãé²ããã³ãŒããç°¡æœã«ããŸãã
- å
±æãå¿
èŠãªæã ã std::shared_ptrãéåç
§ã«ã¯ std::weak_ptr: è€æ°ã®æã¡äž»ããããªãœãŒã¹ã«ã¯åç
§ã«ãŠã³ãã䜿ããçžäºåç
§ã«ãã埪ç°åç
§ãªãŒã¯ã¯ weak_ptr ã§æã¡åããŸãã
- ã³ã³ããã®æ¶å»ãšã¡ã¢ãªè§£æŸã®åæ: vector<unique_ptr<T>> ãã erase ããã ãã§ããŒãå®äœã峿èªåè§£æŸãããæå delete ã1è¡ãèŠããªããªããŸãã
ð ç解床ãã§ãã¯ã¯ã€ãº
Q1. std::unique_ptr ã§ãã³ããŒïŒä»£å
¥ãåŒæ°ã®å€æž¡ãïŒããã³ã³ãã€ã«ãšã©ãŒã«ãªãæå€§ã®çç±ã¯äœã§ããïŒ
- 1. ã³ã³ãã€ã©ãã³ããŒçšã®ã¡ã¢ãªã確ä¿ããã®ã«æéãããããã
- 2. 2ã€ã®ãã€ã³ã¿ãåãå®äœãæããšãç Žæ£æã«2å deleteïŒäºéè§£æŸïŒãããŠã¯ã©ãã·ã¥ãããã
- 3. C++11以éã§ã¯ãã¹ãŠã®ã¯ã©ã¹ã§ã³ããŒãçŠæ¢ããããã
- 4. ä»®æ³é¢æ°ããŒãã«ïŒvtableïŒã®ãµã€ãºã2åã«ãªã£ãŠããŸããã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒ2ã€ã®ãã€ã³ã¿ãåãå®äœãæããšãç Žæ£æã«2å deleteïŒäºéè§£æŸïŒãããŠã¯ã©ãã·ã¥ãããã
æ£è§£ã¯ã2ã€ã®ãã€ã³ã¿ãåãå®äœãæããšãç Žæ£æã«2å deleteïŒäºéè§£æŸïŒãããŠã¯ã©ãã·ã¥ãããããã§ããunique_ptr ã¯ãå¯äžã®ææè
ãã§ããããšãä¿èšŒããããã³ããŒã³ã³ã¹ãã©ã¯ã¿ãåé€ãããŠããŸããæææš©ãæž¡ãã«ã¯ std::move() ãçšããŸãã
Q2. std::unique_ptr<Enemy> p2 = std::move(p1); ãå®è¡ããçŽåŸãå
ã®å€æ° p1 ã®å€ã¯ã©ããªããŸããïŒ
- 1. p2 ãšåãããŒãã¢ãã¬ã¹ãæãç¶ãã
- 2. èªåçã« delete ãããŠæªå®çŸ©ã®äžæ£ãã€ã³ã¿ã«ãªã
- 3. nullptrïŒç©ºãã€ã³ã¿ïŒã«ãªã
- 4. ã³ã³ãã€ã«ãšã©ãŒã«ãªãå®è¡ã§ããªã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒnullptrïŒç©ºãã€ã³ã¿ïŒã«ãªã
æ£è§£ã¯ãnullptrïŒç©ºãã€ã³ã¿ïŒã«ãªããã§ããã ãŒãã«ãã£ãŠæææš©ã p2 ã«å®å
šã«ç§»è²ããããããå
ã® p1 ã¯å®å
šã«ãªã»ããïŒnullptrïŒãããäºéè§£æŸã誀æäœãé²ããŸãã
Q3. std::shared_ptr<T> ãããŒãäžã®å®äœã delete è§£æŸããã®ã¯ã©ã®ã¿ã€ãã³ã°ã§ããïŒ
- 1. ããã°ã©ã å
šäœïŒmain颿°ïŒãçµäºãããšã
- 2. ãããã1ã€ã® shared_ptr ãã¹ã³ãŒããæãããšã
- 3. ãã®å®äœãæããã¹ãŠã® shared_ptr ãç Žæ£ãããåç
§ã«ãŠã³ãïŒuse_countïŒã 0 ã«ãªã£ããšã
- 4. ã¬ããŒãžã³ã¬ã¯ã¿ã宿巡åããŠååãããšã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒãã®å®äœãæããã¹ãŠã® shared_ptr ãç Žæ£ãããåç
§ã«ãŠã³ãïŒuse_countïŒã 0 ã«ãªã£ããšã
æ£è§£ã¯ãåç
§ã«ãŠã³ãïŒuse_countïŒã 0 ã«ãªã£ããšããã§ããæåŸã®ææè
ãã¹ã³ãŒããæããŠã«ãŠã³ãã 0 ã«ãªã£ãç¬éã«ãå³åº§ã«å®äœã®ãã¹ãã©ã¯ã¿ãåŒã°ããŠã¡ã¢ãªãè¿åŽãããŸãã
Q4. ãªããžã§ã¯ãAãšãªããžã§ã¯ãBãäºãã« shared_ptr ã§ææãåãããšã§ãã¡ã¢ãªãæ°žé ã«è§£æŸãããªããªãçŸè±¡ãäœãšåŒã³ãã©ã解決ããŸããïŒ
- 1. 埪ç°åç
§ïŒCyclic ReferenceïŒãçæ¹ã std::weak_ptr ã«ããŠæææš©ã®èŒªãæã¡åãã
- 2. ãã³ã°ãªã³ã°ãã€ã³ã¿ãäž¡æ¹ã« raw ãã€ã³ã¿ã䜿ãããšã§è§£æ±ºããã
- 3. ã¡ã¢ãªãã©ã°ã¡ã³ããŒã·ã§ã³ãstd::make_shared ã䜿ãããšã§è§£æ±ºããã
- 4. äºéè§£æŸãåºåºã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ã virtual ã«ããããšã§è§£æ±ºããã
æ£è§£ãšè§£èª¬ãèŠã
æ£è§£ïŒåŸªç°åç
§ïŒCyclic ReferenceïŒãçæ¹ã std::weak_ptr ã«ããŠæææš©ã®èŒªãæã¡åãã
æ£è§£ã¯ã埪ç°åç
§ïŒCyclic ReferenceïŒãçæ¹ã std::weak_ptr ã«ããŠæææš©ã®èŒªãæã¡åããã§ããweak_ptr ã¯åç
§ã«ãŠã³ã¿ãå¢ãããªããèŠå®ãå°çšãã®ãã€ã³ã¿ã§ããããã埪ç°åç
§ã«ããæ»ã®ããã¯ãå®å
šã«é²ãããšãã§ããŸãã
ð»ââïž ã·ãã¯ãC++ã©ã ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ã·ã¹ãã
ãã©ãŠã¶ã§JavaScriptãæå¹ã«ãããšããã©ãŠã¶å
ã€ã³ããŒããŒã²ãŒã ãšãã¥ã¬ãŒã¿ãã¡ã¢ãªãããå¯èŠåãUMLã¯ã©ã¹å³ã察話å解説ãç解床ã¯ã€ãºãèµ·åããŸãã
ã€ã³ã¿ã©ã¯ãã£ãåŠç¿ãéå§ãã â