読者です 読者をやめる 読者になる 読者になる

きままにブログ

プログラミングを主とした私のメモ帳です。寂しいのでコメントください笑

コンテナクラスとコンテナの関係

要件

あるコンテナクラスCCがあって、要素のクラスCをリンクリストとして可変子保持する。各クラスCは適当なタイミングで自身を削除したい。どうすべきか?

クラスCに親の参照を持たせ、自身の削除が必要になったところで親に自信を削除するように通知する。この案には無駄が2つある。

  • eraseするのに線形探索が必要
  • 各Cは親への参照として、アドレス分(32bitあるいは64bit)のメモリを消費する(C++コンパイラが多い)。
#include <iostream>
#include <list>
#include <memory>

class C;

class CC {
public:
	void add(int id);
	void list();
	void callEraseAt(int id);
	void erase(std::unique_ptr<C>::pointer object);

private:
	std::list<std::unique_ptr<C>> ml;
};

class C {
public:
	int id;

	C(CC& parent, int id) : parent(parent), id(id) {
		std::cout << "create(" << id << ")" << std::endl;
	}

	void callDestroy() {
		std::cout << "callDestory()" << std::endl;
		parent.erase(this);
	}

	~C() {
		std::cout << "destroy(" << id << ")" << std::endl;
	}

	C& operator=(const C&) = delete;

private:
	CC& parent; // 無駄な領域??
};

void CC::add(int id) {
	ml.push_back(std::make_unique<C>(*this, id));
}

void CC::list() {
	for(auto& e : ml) {
		std::cout << e->id << std::endl;
	}
}

void CC::erase(std::unique_ptr<C>::pointer object) {
	for(auto it = ml.begin(); it != ml.end();) {
		if((*it).get() == object) {
			it = ml.erase(it);
			continue;
		}
		++it;
	}
}

void CC::callEraseAt(int id) {
	for(auto& e : ml) {
		if(e->id == id) {
			e->callDestroy();
			break;
		}
	}
}

int main() {
	CC cc;

	cc.add(1);
	cc.add(2);
	cc.add(3);
	cc.add(4);

	cc.callEraseAt(3);

	cc.list();

	std::cin.get();
	return 0;
}