intrusiveという用語は、リストやスタックなどのデータ構造を表すのに使用されていますが、どういう意味ですか?
侵入型データ構造のコード例を教えてください。また、非侵入型データ構造との違いを教えてください。
また、なぜ侵入型(または非侵入型)にするのですか?利点は何ですか?欠点は何ですか?
侵入型データ構造は、それらを格納するために、格納しようとしている要素の助けを必要とするものです。
言い替えさせてください。そのデータ構造に何かを入れると、その「何か」は、何らかの形でそのデータ構造にあるという事実に気づきます。データ構造に要素を追加すると、要素が変更されます。
たとえば、各ノードが左右のサブツリーへの参照と、そのノードの要素値への参照を持つ、非侵入型のバイナリツリーを構築できます。
または、これらのサブツリーへの参照が値自体に埋め込まれている、侵入型のものを構築できます。
侵入型データ構造の例は、変更可能な要素の順序付きリストです。要素が変更された場合、リストを並べ替える必要があるため、リストオブジェクトは、要素の協力を得るために要素のプライバシーを侵害する必要があります。すなわち。要素は、それが含まれているリストについて知っており、変更を通知する必要があります。
ORMシステムは通常、侵入的なデータ構造を中心に展開し、オブジェクトの大きなリストに対する反復を最小限に抑えます。たとえば、データベース内のすべての従業員のリストを取得し、そのうちの1人の名前を変更し、それをデータベースに保存する場合、従業員オブジェクトが変更されたときに従業員の侵入リストが通知されます。オブジェクトはそれがどのリストにあるかを知っています。
邪魔にならないリストは通知されず、何が変更され、どのように変更されたかを把握する必要があります。
侵入型コンテナでは、データ自体がコンテナに必要な情報を保存します。つまり、一方ではデータの保存方法に応じてデータ型を特化する必要があり、他方では、データが保存方法を「認識」しているため、わずかに最適化できることを意味します。
非侵入型:
template<typename T>
class LinkedList
{
struct ListItem
{
T Value;
ListItem* Prev;
ListItem* Next;
};
ListItem* FirstItem;
ListItem* LastItem;
[...]
ListItem* append(T&& val)
{
LastItem = LastItem.Next = new ListItem{val, LastItem, nullptr};
};
};
LinkedList<int> IntList;
侵入:
template<typename T>
class LinkedList
{
T* FirstItem;
T* LastItem;
[...]
T* append(T&& val)
{
T* newValue = new T(val);
newValue.Next = nullptr;
newValue.Prev = LastItem;
LastItem.Next = newValue;
LastItem = newValue;
};
};
struct IntListItem
{
int Value;
IntListItem* Prev;
IntListItem* Next;
};
LinkedList<IntListItem> IntList;
個人的には、透明性のために押し付けがましいデザインが好きです。