OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libstdc++-v3/] [doc/] [xml/] [manual/] [containers.xml] - Blame information for rev 826

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 424 jeremybenn
2
3
 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
4
[ ]>
5
 
6
7
8
 
9
10
  
11
    
12
      ISO C++
13
    
14
    
15
      library
16
    
17
  
18
19
 
20
</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>21</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>  Containers</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>22</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>  <indexterm><primary>Containers</primary></indexterm></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>23</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>
24
 
25
26
27
28
  Sequences
29
 
30
31
32
  list
33
  
34
    list::size() is O(n)
35
   
36
     Yes it is, and that's okay.  This is a decision that we preserved
37
     when we imported SGI's STL implementation.  The following is
38
     quoted from 
39
     url="http://www.sgi.com/tech/stl/FAQ.html">their FAQ:
40
   
41
   
42
     
43
       The size() member function, for list and slist, takes time
44
       proportional to the number of elements in the list.  This was a
45
       deliberate tradeoff.  The only way to get a constant-time
46
       size() for linked lists would be to maintain an extra member
47
       variable containing the list's size.  This would require taking
48
       extra time to update that variable (it would make splice() a
49
       linear time operation, for example), and it would also make the
50
       list larger.  Many list algorithms don't require that extra
51
       word (algorithms that do require it might do better with
52
       vectors than with lists), and, when it is necessary to maintain
53
       an explicit size count, it's something that users can do
54
       themselves.
55
     
56
     
57
       This choice is permitted by the C++ standard. The standard says
58
       that size() should be constant time, and
59
       should does not mean the same thing as
60
       shall.  This is the officially recommended ISO
61
       wording for saying that an implementation is supposed to do
62
       something unless there is a good reason not to.
63
      
64
      
65
        One implication of linear time size(): you should never write
66
      
67
         
68
         if (L.size() == 0)
69
             ...
70
         
71
 
72
         
73
         Instead, you should write
74
         
75
 
76
         
77
         if (L.empty())
78
             ...
79
         
80
   
81
  
82
83
 
84
85
86
  vector
87
  
88
  
89
  
90
    Space Overhead Management
91
   
92
     In 
93
     url="http://gcc.gnu.org/ml/libstdc++/2002-04/msg00105.html">this
94
     message to the list, Daniel Kostecky announced work on an
95
     alternate form of std::vector that would support
96
     hints on the number of elements to be over-allocated.  The design
97
     was also described, along with possible implementation choices.
98
   
99
   
100
     The first two alpha releases were announced 
101
     url="http://gcc.gnu.org/ml/libstdc++/2002-07/msg00048.html">here
102
     and 
103
     url="http://gcc.gnu.org/ml/libstdc++/2002-07/msg00111.html">here.
104
   
105
 
106
  
107
108
 
109
110
111
112
  Associative
113
 
114
  
115
    Insertion Hints
116
   
117
     Section [23.1.2], Table 69, of the C++ standard lists this
118
     function for all of the associative containers (map, set, etc):
119
   
120
   
121
      a.insert(p,t);
122
   
123
   
124
     where 'p' is an iterator into the container 'a', and 't' is the
125
     item to insert.  The standard says that t is
126
     inserted as close as possible to the position just prior to
127
     p. (Library DR #233 addresses this topic,
128
     referring to 
129
     url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html">N1780.
130
     Since version 4.2 GCC implements the resolution to DR 233, so
131
     that insertions happen as close as possible to the hint. For
132
     earlier releases the hint was only used as described below.
133
   
134
   
135
     Here we'll describe how the hinting works in the libstdc++
136
     implementation, and what you need to do in order to take
137
     advantage of it.  (Insertions can change from logarithmic
138
     complexity to amortized constant time, if the hint is properly
139
     used.)  Also, since the current implementation is based on the
140
     SGI STL one, these points may hold true for other library
141
     implementations also, since the HP/SGI code is used in a lot of
142
     places.
143
   
144
   
145
     In the following text, the phrases greater
146
     than and less than refer to the
147
     results of the strict weak ordering imposed on the container by
148
     its comparison object, which defaults to (basically)
149
     <.  Using those phrases is semantically sloppy,
150
     but I didn't want to get bogged down in syntax.  I assume that if
151
     you are intelligent enough to use your own comparison objects,
152
     you are also intelligent enough to assign greater
153
     and lesser their new meanings in the next
154
     paragraph.  *grin*
155
   
156
   
157
     If the hint parameter ('p' above) is equivalent to:
158
   
159
     
160
      
161
        
162
          begin(), then the item being inserted should
163
          have a key less than all the other keys in the container.
164
          The item will be inserted at the beginning of the container,
165
          becoming the new entry at begin().
166
      
167
      
168
      
169
        
170
          end(), then the item being inserted should have
171
          a key greater than all the other keys in the container.  The
172
          item will be inserted at the end of the container, becoming
173
          the new entry before end().
174
      
175
      
176
      
177
        
178
          neither begin() nor end(), then:
179
          Let h be the entry in the container pointed to
180
          by hint, that is, h = *hint.  Then
181
          the item being inserted should have a key less than that of
182
          h, and greater than that of the item preceding
183
          h.  The new item will be inserted between
184
          h and h's predecessor.
185
          
186
      
187
     
188
   
189
     For multimap and multiset, the
190
     restrictions are slightly looser: greater than
191
     should be replaced by not less thanand less
192
     than should be replaced by not greater
193
     than. (Why not replace greater with
194
     greater-than-or-equal-to?  You probably could in your head, but
195
     the mathematicians will tell you that it isn't the same thing.)
196
   
197
   
198
     If the conditions are not met, then the hint is not used, and the
199
     insertion proceeds as if you had called  a.insert(t)
200
      instead.  (Note  that GCC releases
201
     prior to 3.0.2 had a bug in the case with hint ==
202
     begin() for the map and set
203
     classes.  You should not use a hint argument in those releases.)
204
   
205
   
206
     This behavior goes well with other containers'
207
     insert() functions which take an iterator: if used,
208
     the new item will be inserted before the iterator passed as an
209
     argument, same as the other containers.
210
   
211
   
212
     Note  also that the hint in this
213
     implementation is a one-shot.  The older insertion-with-hint
214
     routines check the immediately surrounding entries to ensure that
215
     the new item would in fact belong there.  If the hint does not
216
     point to the correct place, then no further local searching is
217
     done; the search begins from scratch in logarithmic time.
218
   
219
  
220
 
221
 
222
  
223
    
224
    bitset
225
    
226
      Size Variable
227
      
228
        No, you cannot write code of the form
229
      
230
      
231
   
232
      #include <bitset>
233
 
234
      void foo (size_t n)
235
      {
236
          std::bitset<n>   bits;
237
          ....
238
      }
239
   
240
   
241
     because n must be known at compile time.  Your
242
     compiler is correct; it is not a bug.  That's the way templates
243
     work.  (Yes, it is a feature.)
244
   
245
   
246
     There are a couple of ways to handle this kind of thing.  Please
247
     consider all of them before passing judgement.  They include, in
248
     no chaptericular order:
249
   
250
      
251
        A very large N in bitset<N>.
252
        A container<bool>.
253
        Extremely weird solutions.
254
      
255
   
256
     A very large N in
257
     bitset<N>.   It has been
258
     pointed out a few times in newsgroups that N bits only takes up
259
     (N/8) bytes on most systems, and division by a factor of eight is
260
     pretty impressive when speaking of memory.  Half a megabyte given
261
     over to a bitset (recall that there is zero space overhead for
262
     housekeeping info; it is known at compile time exactly how large
263
     the set is) will hold over four million bits.  If you're using
264
     those bits as status flags (e.g.,
265
     changed/unchanged flags), that's a
266
     lot of state.
267
   
268
   
269
     You can then keep track of the maximum bit used
270
     during some testing runs on representative data, make note of how
271
     many of those bits really need to be there, and then reduce N to
272
     a smaller number.  Leave some extra space, of course.  (If you
273
     plan to write code like the incorrect example above, where the
274
     bitset is a local variable, then you may have to talk your
275
     compiler into allowing that much stack space; there may be zero
276
     space overhead, but it's all allocated inside the object.)
277
   
278
   
279
     A container<bool>.   The
280
     Committee made provision for the space savings possible with that
281
     (N/8) usage previously mentioned, so that you don't have to do
282
     wasteful things like Container<char> or
283
     Container<short int>.  Specifically,
284
     vector<bool> is required to be specialized for
285
     that space savings.
286
   
287
   
288
     The problem is that vector<bool> doesn't
289
     behave like a normal vector anymore.  There have been
290
     journal articles which discuss the problems (the ones by Herb
291
     Sutter in the May and July/August 1999 issues of C++ Report cover
292
     it well).  Future revisions of the ISO C++ Standard will change
293
     the requirement for vector<bool>
294
     specialization.  In the meantime, deque<bool>
295
     is recommended (although its behavior is sane, you probably will
296
     not get the space savings, but the allocation scheme is different
297
     than that of vector).
298
   
299
   
300
     Extremely weird solutions.   If
301
     you have access to the compiler and linker at runtime, you can do
302
     something insane, like figuring out just how many bits you need,
303
     then writing a temporary source code file.  That file contains an
304
     instantiation of bitset for the required number of
305
     bits, inside some wrapper functions with unchanging signatures.
306
     Have your program then call the compiler on that file using
307
     Position Independent Code, then open the newly-created object
308
     file and load those wrapper functions.  You'll have an
309
     instantiation of bitset<N> for the exact
310
     N that you need at the time.  Don't forget to delete
311
     the temporary files.  (Yes, this can be, and
312
     has been, done.)
313
   
314
   
315
   
316
     This would be the approach of either a visionary genius or a
317
     raving lunatic, depending on your programming and management
318
     style.  Probably the latter.
319
   
320
   
321
     Which of the above techniques you use, if any, are up to you and
322
     your intended application.  Some time/space profiling is
323
     indicated if it really matters (don't just guess).  And, if you
324
     manage to do anything along the lines of the third category, the
325
     author would love to hear from you...
326
   
327
   
328
     Also note that the implementation of bitset used in libstdc++ has
329
     some extensions.
330
   
331
 
332
    
333
    
334
      Type String
335
      
336
      
337
   
338
     Bitmasks do not take char* nor const char* arguments in their
339
     constructors.  This is something of an accident, but you can read
340
     about the problem: follow the library's Links from
341
     the homepage, and from the C++ information defect
342
     reflector link, select the library issues list.  Issue
343
     number 116 describes the problem.
344
   
345
   
346
     For now you can simply make a temporary string object using the
347
     constructor expression:
348
   
349
   
350
      std::bitset<5> b ( std::string(10110) );
351
   
352
 
353
   
354
     instead of
355
   
356
 
357
    
358
      std::bitset<5> b ( 10110 );    // invalid
359
    
360
    
361
  
362
 
363
364
 
365
366
367
368
  Interacting with C
369
 
370
  
371
    Containers vs. Arrays
372
   
373
     You're writing some code and can't decide whether to use builtin
374
     arrays or some kind of container.  There are compelling reasons
375
     to use one of the container classes, but you're afraid that
376
     you'll eventually run into difficulties, change everything back
377
     to arrays, and then have to change all the code that uses those
378
     data types to keep up with the change.
379
   
380
   
381
     If your code makes use of the standard algorithms, this isn't as
382
     scary as it sounds.  The algorithms don't know, nor care, about
383
     the kind of container on which they work, since
384
     the algorithms are only given endpoints to work with.  For the
385
     container classes, these are iterators (usually
386
     begin() and end(), but not always).
387
     For builtin arrays, these are the address of the first element
388
     and the past-the-end element.
389
   
390
   
391
     Some very simple wrapper functions can hide all of that from the
392
     rest of the code.  For example, a pair of functions called
393
     beginof can be written, one that takes an array,
394
     another that takes a vector.  The first returns a pointer to the
395
     first element, and the second returns the vector's
396
     begin() iterator.
397
   
398
   
399
     The functions should be made template functions, and should also
400
     be declared inline.  As pointed out in the comments in the code
401
     below, this can lead to beginof being optimized out
402
     of existence, so you pay absolutely nothing in terms of increased
403
     code size or execution time.
404
   
405
   
406
     The result is that if all your algorithm calls look like
407
   
408
   
409
   std::transform(beginof(foo), endof(foo), beginof(foo), SomeFunction);
410
   
411
   
412
     then the type of foo can change from an array of ints to a vector
413
     of ints to a deque of ints and back again, without ever changing
414
     any client code.
415
   
416
 
417
418
// beginof
419
template<typename T>
420
  inline typename vector<T>::iterator
421
  beginof(vector<T> &v)
422
  { return v.begin(); }
423
 
424
template<typename T, unsigned int sz>
425
  inline T*
426
  beginof(T (&array)[sz]) { return array; }
427
 
428
// endof
429
template<typename T>
430
  inline typename vector<T>::iterator
431
  endof(vector<T> &v)
432
  { return v.end(); }
433
 
434
template<typename T, unsigned int sz>
435
  inline T*
436
  endof(T (&array)[sz]) { return array + sz; }
437
 
438
// lengthof
439
template<typename T>
440
  inline typename vector<T>::size_type
441
  lengthof(vector<T> &v)
442
  { return v.size(); }
443
 
444
template<typename T, unsigned int sz>
445
  inline unsigned int
446
  lengthof(T (&)[sz]) { return sz; }
447
448
 
449
   
450
     Astute readers will notice two things at once: first, that the
451
     container class is still a vector<T> instead
452
     of a more general Container<T>.  This would
453
     mean that three functions for deque would have to be
454
     added, another three for list, and so on.  This is
455
     due to problems with getting template resolution correct; I find
456
     it easier just to give the extra three lines and avoid confusion.
457
   
458
   
459
     Second, the line
460
   
461
   
462
    inline unsigned int lengthof (T (&)[sz]) { return sz; }
463
   
464
   
465
     looks just weird!  Hint:  unused parameters can be left nameless.
466
   
467
  
468
 
469
470
 
471

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.