• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5<title>Intrusive and non-intrusive containers</title>
6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
9<link rel="up" href="../intrusive.html" title="Chapter 19. Boost.Intrusive">
10<link rel="prev" href="../intrusive.html" title="Chapter 19. Boost.Intrusive">
11<link rel="next" href="usage.html" title="How to use Boost.Intrusive">
12</head>
13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
14<table cellpadding="2" width="100%"><tr>
15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
16<td align="center"><a href="../../../index.html">Home</a></td>
17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
20<td align="center"><a href="../../../more/index.htm">More</a></td>
21</tr></table>
22<hr>
23<div class="spirit-nav">
24<a accesskey="p" href="../intrusive.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../intrusive.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="usage.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
25</div>
26<div class="section">
27<div class="titlepage"><div><div><h2 class="title" style="clear: both">
28<a name="intrusive.intrusive_vs_nontrusive"></a><a class="link" href="intrusive_vs_nontrusive.html" title="Intrusive and non-intrusive containers">Intrusive and non-intrusive
29    containers</a>
30</h2></div></div></div>
31<div class="toc"><dl class="toc">
32<dt><span class="section"><a href="intrusive_vs_nontrusive.html#intrusive.intrusive_vs_nontrusive.differences_intrusive_vs_nontrusive">Differences
33      between intrusive and non-intrusive containers</a></span></dt>
34<dt><span class="section"><a href="intrusive_vs_nontrusive.html#intrusive.intrusive_vs_nontrusive.properties_of_intrusive">Properties
35      of Boost.Intrusive containers</a></span></dt>
36</dl></div>
37<div class="section">
38<div class="titlepage"><div><div><h3 class="title">
39<a name="intrusive.intrusive_vs_nontrusive.differences_intrusive_vs_nontrusive"></a><a class="link" href="intrusive_vs_nontrusive.html#intrusive.intrusive_vs_nontrusive.differences_intrusive_vs_nontrusive" title="Differences between intrusive and non-intrusive containers">Differences
40      between intrusive and non-intrusive containers</a>
41</h3></div></div></div>
42<p>
43        The main difference between intrusive containers and non-intrusive containers
44        is that in C++ non-intrusive containers store <span class="bold"><strong>copies</strong></span>
45        of values passed by the user. Containers use the <code class="computeroutput"><span class="identifier">Allocator</span></code>
46        template parameter to allocate the stored values:
47      </p>
48<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">list</span><span class="special">&gt;</span>
49<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">assert</span><span class="special">.</span><span class="identifier">h</span><span class="special">&gt;</span>
50
51<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
52<span class="special">{</span>
53   <span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">MyClass</span><span class="special">&gt;</span> <span class="identifier">myclass_list</span><span class="special">;</span>
54
55   <span class="identifier">MyClass</span> <span class="identifier">myclass</span><span class="special">(...);</span>
56   <span class="identifier">myclass_list</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">myclass</span><span class="special">);</span>
57
58   <span class="comment">//The stored object is different from the original object</span>
59   <span class="identifier">assert</span><span class="special">(&amp;</span><span class="identifier">myclass</span> <span class="special">!=</span> <span class="special">&amp;</span><span class="identifier">myclass_list</span><span class="special">.</span><span class="identifier">front</span><span class="special">());</span>
60   <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
61<span class="special">}</span>
62</pre>
63<p>
64        To store the newly allocated copy of <code class="computeroutput"><span class="identifier">myclass</span></code>,
65        the container needs additional data: <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span></code>
66        usually allocates nodes that contain pointers to the next and previous node
67        and the value itself. Something similar to:
68      </p>
69<pre class="programlisting"><span class="comment">//A possible implementation of a std::list&lt;MyClass&gt; node</span>
70<span class="keyword">class</span> <span class="identifier">list_node</span>
71<span class="special">{</span>
72   <span class="identifier">list_node</span> <span class="special">*</span><span class="identifier">next</span><span class="special">;</span>
73   <span class="identifier">list_node</span> <span class="special">*</span><span class="identifier">previous</span><span class="special">;</span>
74   <span class="identifier">MyClass</span>    <span class="identifier">value</span><span class="special">;</span>
75<span class="special">};</span>
76</pre>
77<p>
78        On the other hand, an intrusive container does not store copies of passed
79        objects, but it stores the objects themselves. The additional data needed
80        to insert the object in the container must be provided by the object itself.
81        For example, to insert <code class="computeroutput"><span class="identifier">MyClass</span></code>
82        in an intrusive container that implements a linked list, <code class="computeroutput"><span class="identifier">MyClass</span></code>
83        must contain the needed <span class="emphasis"><em>next</em></span> and <span class="emphasis"><em>previous</em></span>
84        pointers:
85      </p>
86<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">MyClass</span>
87<span class="special">{</span>
88   <span class="identifier">MyClass</span> <span class="special">*</span><span class="identifier">next</span><span class="special">;</span>
89   <span class="identifier">MyClass</span> <span class="special">*</span><span class="identifier">previous</span><span class="special">;</span>
90   <span class="comment">//Other members...</span>
91<span class="special">};</span>
92
93<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
94<span class="special">{</span>
95   <span class="identifier">acme_intrusive_list</span><span class="special">&lt;</span><span class="identifier">MyClass</span><span class="special">&gt;</span> <span class="identifier">list</span><span class="special">;</span>
96
97   <span class="identifier">MyClass</span> <span class="identifier">myclass</span><span class="special">;</span>
98   <span class="identifier">list</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">myclass</span><span class="special">);</span>
99
100   <span class="comment">//"myclass" object is stored in the list</span>
101   <span class="identifier">assert</span><span class="special">(&amp;</span><span class="identifier">myclass</span> <span class="special">==</span> <span class="special">&amp;</span><span class="identifier">list</span><span class="special">.</span><span class="identifier">front</span><span class="special">());</span>
102   <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
103<span class="special">}</span>
104</pre>
105<p>
106        As we can see, knowing which additional data the class should contain is
107        not an easy task. <span class="bold"><strong>Boost.Intrusive</strong></span> offers
108        several intrusive containers and an easy way to make user classes compatible
109        with those containers.
110      </p>
111</div>
112<div class="section">
113<div class="titlepage"><div><div><h3 class="title">
114<a name="intrusive.intrusive_vs_nontrusive.properties_of_intrusive"></a><a class="link" href="intrusive_vs_nontrusive.html#intrusive.intrusive_vs_nontrusive.properties_of_intrusive" title="Properties of Boost.Intrusive containers">Properties
115      of Boost.Intrusive containers</a>
116</h3></div></div></div>
117<p>
118        Semantically, a <span class="bold"><strong>Boost.Intrusive</strong></span> container
119        is similar to a STL container holding pointers to objects. That is, if you
120        have an intrusive list holding objects of type <code class="computeroutput"><span class="identifier">T</span></code>,
121        then <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">*&gt;</span></code>
122        would allow you to do quite the same operations (maintaining and navigating
123        a set of objects of type T and types derived from it).
124      </p>
125<p>
126        A non-intrusive container has some limitations:
127      </p>
128<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
129<li class="listitem">
130            An object can only belong to one container: If you want to share an object
131            between two containers, you either have to store multiple copies of those
132            objects or you need to use containers of pointers: <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">Object</span><span class="special">*&gt;</span></code>.
133          </li>
134<li class="listitem">
135            The use of dynamic allocation to create copies of passed values can be
136            a performance and size bottleneck in some applications. Normally, dynamic
137            allocation imposes a size overhead for each allocation to store bookkeeping
138            information and a synchronization to protected concurrent allocation
139            from different threads.
140          </li>
141<li class="listitem">
142            Before C++11, only copies of objects could be stored in non-intrusive
143            containers. Still copy or move constructors and copy or move assignment
144            operators are required and non-copyable and non-movable objects can't
145            be stored in some containers. In any case, <span class="bold"><strong>new</strong></span>
146            objects have to be created inside the container using constructors and
147            the same object can't be shared between two containers.
148          </li>
149<li class="listitem">
150            It's not possible to store a derived object in a STL-container while
151            retaining its original type.
152          </li>
153</ul></div>
154<p>
155        Intrusive containers have some important advantages:
156      </p>
157<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
158<li class="listitem">
159            Operating with intrusive containers doesn't invoke any memory management
160            at all. The time and size overhead associated with dynamic memory can
161            be minimized.
162          </li>
163<li class="listitem">
164            The same object can be inserted in more than one container at the same
165            time with a tiny overhead in the object size.
166          </li>
167<li class="listitem">
168            Iterating an Intrusive container needs less memory accesses than the
169            semantically equivalent container of pointers: iteration is faster.
170          </li>
171<li class="listitem">
172            Intrusive containers offer better exception guarantees than non-intrusive
173            containers. In some situations intrusive containers offer a no-throw
174            guarantee that can't be achieved with non-intrusive containers.
175          </li>
176<li class="listitem">
177            The computation of an iterator to an element from a pointer or reference
178            to that element is a constant time operation (computing the position
179            of <code class="computeroutput"><span class="identifier">T</span><span class="special">*</span></code>
180            in a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">*&gt;</span></code>
181            has linear complexity).
182          </li>
183<li class="listitem">
184            Intrusive containers offer predictability when inserting and erasing
185            objects since no memory management is done with intrusive containers.
186            Memory management usually is not a predictable operation so complexity
187            guarantees from non-intrusive containers are looser than the guarantees
188            offered by intrusive containers.
189          </li>
190</ul></div>
191<p>
192        Intrusive containers have also downsides:
193      </p>
194<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
195<li class="listitem">
196            Each type stored in an intrusive container needs additional memory holding
197            the maintenance information needed by the container. Hence, whenever
198            a certain type will be stored in an intrusive container <span class="bold"><strong>you
199            have to change the definition of that type</strong></span> appropriately.
200            Although this task is easy with <span class="bold"><strong>Boost.Intrusive</strong></span>,
201            touching the definition of a type is sometimes a crucial issue.
202          </li>
203<li class="listitem">
204            In intrusive containers you don't store a copy of an object, <span class="bold"><strong>but rather the original object is linked with other objects
205            in the container</strong></span>. Objects don't need copy-constructors or
206            assignment operators to be stored in intrusive containers. But you have
207            to take care of possible side effects, whenever you change the contents
208            of an object (this is especially important for associative containers).
209          </li>
210<li class="listitem">
211            The user <span class="bold"><strong>has to manage the lifetime of inserted
212            objects</strong></span> independently from the containers.
213          </li>
214<li class="listitem">
215            Again you have to be <span class="bold"><strong>careful</strong></span>: in contrast
216            to STL containers <span class="bold"><strong>it's easy to render an iterator
217            invalid</strong></span> without touching the intrusive container directly,
218            because the object can be disposed before is erased from the container.
219          </li>
220<li class="listitem">
221            <span class="bold"><strong>Boost.Intrusive</strong></span> containers are <span class="bold"><strong>non-copyable and non-assignable</strong></span>. Since intrusive
222            containers don't have allocation capabilities, these operations make
223            no sense. However, swapping can be used to implement move capabilities.
224            To ease the implementation of copy constructors and assignment operators
225            of classes storing <span class="bold"><strong>Boost.Intrusive</strong></span> containers,
226            <span class="bold"><strong>Boost.Intrusive</strong></span> offers special cloning
227            functions. See <a class="link" href="clone_from.html" title="Cloning Boost.Intrusive containers">Cloning Boost.Intrusive
228            containers</a> section for more information.
229          </li>
230<li class="listitem">
231            Analyzing the thread safety of a program that uses containers is harder
232            with intrusive containers, because the container might be modified indirectly
233            without an explicit call to a container member.
234          </li>
235</ul></div>
236<div class="table">
237<a name="intrusive.intrusive_vs_nontrusive.properties_of_intrusive.summary_of_intrusive_containers_"></a><p class="title"><b>Table 19.1. Summary of intrusive containers advantages and disadvantages</b></p>
238<div class="table-contents"><table class="table" summary="Summary of intrusive containers advantages and disadvantages">
239<colgroup>
240<col>
241<col>
242<col>
243</colgroup>
244<thead><tr>
245<th>
246                <p>
247                  Issue
248                </p>
249              </th>
250<th>
251                <p>
252                  Intrusive
253                </p>
254              </th>
255<th>
256                <p>
257                  Non-intrusive
258                </p>
259              </th>
260</tr></thead>
261<tbody>
262<tr>
263<td>
264                <p>
265                  Memory management
266                </p>
267              </td>
268<td>
269                <p>
270                  External
271                </p>
272              </td>
273<td>
274                <p>
275                  Internal through allocator
276                </p>
277              </td>
278</tr>
279<tr>
280<td>
281                <p>
282                  Insertion/Erasure time
283                </p>
284              </td>
285<td>
286                <p>
287                  Faster
288                </p>
289              </td>
290<td>
291                <p>
292                  Slower
293                </p>
294              </td>
295</tr>
296<tr>
297<td>
298                <p>
299                  Memory locality
300                </p>
301              </td>
302<td>
303                <p>
304                  Better
305                </p>
306              </td>
307<td>
308                <p>
309                  Worse
310                </p>
311              </td>
312</tr>
313<tr>
314<td>
315                <p>
316                  Can insert the same object in more than one container
317                </p>
318              </td>
319<td>
320                <p>
321                  Yes
322                </p>
323              </td>
324<td>
325                <p>
326                  No
327                </p>
328              </td>
329</tr>
330<tr>
331<td>
332                <p>
333                  Exception guarantees
334                </p>
335              </td>
336<td>
337                <p>
338                  Better
339                </p>
340              </td>
341<td>
342                <p>
343                  Worse
344                </p>
345              </td>
346</tr>
347<tr>
348<td>
349                <p>
350                  Computation of iterator from value
351                </p>
352              </td>
353<td>
354                <p>
355                  Constant
356                </p>
357              </td>
358<td>
359                <p>
360                  Non-constant
361                </p>
362              </td>
363</tr>
364<tr>
365<td>
366                <p>
367                  Insertion/erasure predictability
368                </p>
369              </td>
370<td>
371                <p>
372                  High
373                </p>
374              </td>
375<td>
376                <p>
377                  Low
378                </p>
379              </td>
380</tr>
381<tr>
382<td>
383                <p>
384                  Memory use
385                </p>
386              </td>
387<td>
388                <p>
389                  Minimal
390                </p>
391              </td>
392<td>
393                <p>
394                  More than minimal
395                </p>
396              </td>
397</tr>
398<tr>
399<td>
400                <p>
401                  Insert objects by value retaining polymorphic behavior
402                </p>
403              </td>
404<td>
405                <p>
406                  Yes
407                </p>
408              </td>
409<td>
410                <p>
411                  No (slicing)
412                </p>
413              </td>
414</tr>
415<tr>
416<td>
417                <p>
418                  User must modify the definition of the values to insert
419                </p>
420              </td>
421<td>
422                <p>
423                  Yes
424                </p>
425              </td>
426<td>
427                <p>
428                  No
429                </p>
430              </td>
431</tr>
432<tr>
433<td>
434                <p>
435                  Containers are copyable
436                </p>
437              </td>
438<td>
439                <p>
440                  No
441                </p>
442              </td>
443<td>
444                <p>
445                  Yes
446                </p>
447              </td>
448</tr>
449<tr>
450<td>
451                <p>
452                  Inserted object's lifetime managed by
453                </p>
454              </td>
455<td>
456                <p>
457                  User (more complex)
458                </p>
459              </td>
460<td>
461                <p>
462                  Container (less complex)
463                </p>
464              </td>
465</tr>
466<tr>
467<td>
468                <p>
469                  Container invariants can be broken without using the container
470                </p>
471              </td>
472<td>
473                <p>
474                  Easier
475                </p>
476              </td>
477<td>
478                <p>
479                  Harder (only with containers of pointers)
480                </p>
481              </td>
482</tr>
483<tr>
484<td>
485                <p>
486                  Thread-safety analysis
487                </p>
488              </td>
489<td>
490                <p>
491                  Harder
492                </p>
493              </td>
494<td>
495                <p>
496                  Easier
497                </p>
498              </td>
499</tr>
500</tbody>
501</table></div>
502</div>
503<br class="table-break"><p>
504        For a performance comparison between Intrusive and Non-intrusive containers
505        see <a class="link" href="performance.html" title="Performance">Performance</a> section.
506      </p>
507</div>
508</div>
509<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
510<td align="left"></td>
511<td align="right"><div class="copyright-footer">Copyright © 2005 Olaf Krzikalla<br>Copyright © 2006-2015 Ion Gaztanaga<p>
512        Distributed under the Boost Software License, Version 1.0. (See accompanying
513        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
514      </p>
515</div></td>
516</tr></table>
517<hr>
518<div class="spirit-nav">
519<a accesskey="p" href="../intrusive.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../intrusive.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="usage.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
520</div>
521</body>
522</html>
523