回答:
侵入型データ構造は、それらを格納するために格納しようとしている要素の助けを必要とするものです。
言い換えましょう。そのデータ構造に何かを入れると、その「何か」は、何らかの形でそのデータ構造にあるという事実を認識します。要素をデータ構造に追加すると、要素が変更されます。
たとえば、各ノードが左右のサブツリーへの参照とそのノードの要素値への参照を持つ非侵入型バイナリツリーを構築できます。
または、それらのサブツリーへの参照が値自体に埋め込まれている、煩わしいものを構築することもできます。
煩わしいデータ構造の例は、変更可能な要素の順序付きリストです。要素が変更された場合、リストを並べ替える必要があるため、リストオブジェクトは要素のプライバシーを侵害して要素の協力を得る必要があります。すなわち。要素は、それが含まれているリストを認識し、変更を通知する必要があります。
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;
個人的には、透明性のために押し付けがましいデザインを好みます。