📄 select_iterator.htm
字号:
<td valign="top"><font size="3">See below.</font></td>
</tr>
<tr>
<td valign="top"><tt>DBView::select_iterator(const
DBView::select_iterator&)</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a> </td>
<td valign="top">The copy constructor. <font size="3">See
Note </font><a href="#2"><font size="3">[2]</font></a><font
size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>DBView::select_iterator&
operator=(const DBView select_iterator&)</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a> </td>
<td valign="top">The assignment operator </td>
</tr>
<tr>
<td valign="top"><tt>const DataObj &operator*()</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a></td>
<td valign="top">Dereferencing operator. Returns the <font
size="2" face="Courier New">DataObj </font><font size="3">pointed
to in the </font><font size="2" face="Courier New">DBView</font><font
size="3">. This operator forbids assigning to the
iterator's </font><font size="2" face="Courier New">DataObj.</font></td>
</tr>
<tr>
<td valign="top"><tt>CountedPtr<DataObj> operator->()</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a>, <font size="2" face="Courier New">DB_iterator</font></td>
<td valign="top">Dereferencing operator. Returns a
pointer to the <font size="1" face="Courier New">DataObj </font><font
size="3">read from the </font><font size="2"
face="Courier New">DBView</font><font size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>DBView::select_iterator&
operator++()</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a></td>
<td valign="top">Preincrement. Reads a <font size="2"
face="Courier New">DataObj </font><font size="3">to the </font><font
size="2" face="Courier New">DBView. </font><font size="3">See
Note </font><a href="#1"><font size="3">[1]</font></a><font
size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>const DBView::select_iterator
operator++(int)</tt> </td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a></td>
<td valign="top">Postincrement Reads a <font size="2"
face="Courier New">DataObj </font><font size="3">to the </font><font
size="2" face="Courier New">DBView.</font><font size="3">
See Note </font><a href="#1"><font size="3">[1]</font></a><font
size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>friend bool operator==(const
select_iterator &i1, const select_iterator &i2)</tt>
</td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a></td>
<td valign="top">Returns whether the two iterators are
equal, that is, do they refer to the same<font size="2"
face="Courier New"> DataObj</font>? <font size="3">See
Note </font><a href="#3"><font size="3">[3]</font></a><font
size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>friend bool operator!=(const
select_iterator &i1, const select_iterator &i2)</tt>
</td>
<td valign="top"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a></td>
<td valign="top">Returns whether the two iterators are <strong>not
</strong>equal. Equivalent to <font size="2"
face="Courier New">!(i1 == i2).</font></td>
</tr>
</table>
<h3>New members</h3>
<p>These members are not defined in the <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a> requirements or in <font size="2" face="Courier New">DB_iterator<DataObj,
ParamObj></font>, but are specific to <tt>DBView::select_iterator</tt>.
<table border="2">
<tr>
<th>Function </th>
<th>Description </th>
</tr>
<tr>
<td valign="top"><tt>DBView::select_iterator(DBView<DataObj,
ParamObj> &view)</tt> </td>
<td valign="top">Creates an <font size="2"
face="Courier New">select_iterator </font><font size="3">which
refers to</font><font size="2" face="Courier New"> view</font><font
size="1" face="Courier New">. </font><font size="3">See
Note </font><a href="#2"><font size="3">[2]</font></a><font
size="3">.</font></td>
</tr>
<tr>
<td valign="top"><tt>void swap(DBView::select_iterator
&other)</tt></td>
<td valign="top">Swap <font size="2" face="Courier New">*this</font>
with <font size="2">other</font>.</td>
</tr>
</table>
<h3>Notes</h3>
<p><a name="1"></a>[1] This is the operation that actually reads
the <font size="2" face="Courier New">DataObj </font><font
size="3">from the database via the </font><font size="2"
face="Courier New">DBView</font><font size="3">. Each </font><font
size="2" face="Courier New">DBView::select_iterator</font><font
size="1" face="Courier New"> </font><font size="3">internally
owns a </font><font size="2" face="Courier New">DBStmt</font><font
size="3"> object which is allocated and prepared when the
underlying ODBC statement handle is first needed and not before.
The handle is not opened until absolutely needed in order to make
copying and assigning these iterators an inexpensive operation.
The </font><font size="2" face="Courier New">DBStmt </font><font
size="3">is executed on each call to </font><font size="2"
face="Courier New">operator++()</font><font size="3">, whether
the prefix or postfix version.</font></p>
<p><a name="2"></a>[2] There is also a variant of this
constructor which takes a second argument specifying a dummy
whether the iterator is at the beginning or end of the <font
size="2" face="Courier New">DBView</font><font size="2">. </font><font
size="3">It is used internally and should never be called by the
end user.</font></p>
<p><a name="3"></a>[3] According to the standard, certain
invariants must be maintained for an <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a>. The <font size="2" face="Courier New">select_iterator</font>
implementation both adheres to the following invariants as well
as taking advantage of them (assume <font size="2"
face="Courier New">x</font> and <font size="2" face="Courier New">y
</font>are both <font size="2" face="Courier New">select_iterator's)</font>:</p>
<ul>
<li>Identity: <font size="2" face="Courier New">x == y </font><font
size="3">if and only if</font><font size="2"
face="Courier New"> &*x = &*y.</font><font
size="3"> </font></li>
<li><font size="3">Assignable and Equality Comparable: If you
perform </font><font size="2" face="Courier New">x = y, </font><font
size="3">then </font><font size="2" face="Courier New">x
== y. </font><font size="3">See the comments about
Identity for how this invariant is preserved.</font></li>
<li><font size="3">Increment Equality Not Guaranteed: </font><font
size="2" face="Courier New">x == y </font><font size="3">does
<strong>not</strong> imply </font><font size="2"
face="Courier New">++x == ++y.</font></li>
</ul>
<p><font size="3"><strong>Warning: The following explanation is
not for the faint of heart!</strong></font></p>
<p><font size="3">In a view over a database, the records can
appear in a different order. Thus, there is no true notion of
equality for iterators over a view. However, the standard
requires the Identity invariant to be true. The Assignable and
Equality Comparable invariant must also hold for </font><font
size="2" face="Courier New">select_iterator's </font><font
size="3">according to the standard. Thus, we had to find a way to
give these iterators a notion of equality. To simulate equality,
we added a reference counting scheme for all </font><font
size="2" face="Courier New">DataObj's. </font><font size="3">Upon
the creation of a new iterator using the form of the constructor
which takes a </font><font size="2" face="Courier New">DBView</font><font
size="3"> reference, the </font><font size="2" face="Courier New">DBView
</font><font size="3">creates a new </font><font size="2"
face="Courier New">DataObj </font><font size="3">and the iterator
gets a pointer back to that new</font><font size="2"
face="Courier New"> DataObj.</font><font size="3"> Then, when an
iterator copy constructs off of or gets assigned to by another
iterator, this </font><font size="2" face="Courier New">DataObj </font><font
size="3">pointer gets copied to the new iterator and the iterator
gets the view to increment the reference count for that </font><font
size="2" face="Courier New">DataObj. </font><font size="3">The </font><font
size="2" face="Courier New">operator==()</font><font size="3">
compares two </font><font size="2" face="Courier New">select_iterator's
</font><font size="3">simply by comparing their </font><font
size="2" face="Courier">DataObj</font><font size="2"> </font><font
size="3">pointers. The </font><font size="2" face="Courier New">select_iterator's
</font><font size="3">are equal if and only if these pointers are
equal. When the new </font><font size="2" face="Courier New">select_iterator
</font><font size="3">first increments (that is, it fetches the
next </font><font size="2" face="Courier New">DataObj</font><font
size="3"> from the database), the iterator has the view create a
fresh </font><font size="2" face="Courier New">DataObj </font><font
size="3">(the view decrements the old </font><font size="2"
face="Courier New">DataObj's</font><font size="3"> reference
count of course by one)</font><font size="2" face="Courier New"> </font><font
size="3">for it to point to so that the iterators are
conceptually no longer equal. This form of reference counting and
comparison preserve both invariants. The Increment Equality Not
Guaranteed invariant helped us out a bit. As </font><font
size="2" face="Courier New">x == y </font><font size="3">is not
required to yield </font><font size="2" face="Courier New">++x ==
++y, </font><font size="3">we were able to use the above trick of
throwing away the old </font><font size="2" face="Courier New">DataObj
</font><font size="3">reference and just grabbing a new one upon
the new iterator's first call to </font><font size="2"
face="Courier New">operator++()</font><font size="3">.</font></p>
<p><a name="4"></a>[4] This function is a bit peculiar for <font
size="2" face="Courier New">select_iterator's. </font><font
size="3">For the notion of a </font><font size="2"
face="Courier New">DBView's</font><font size="3"> </font><font
size="2" face="Courier New">begin()</font><font size="3"> and </font><font
size="2" face="Courier">end() </font><font size="3">iterators,</font><font
size="2" face="Courier New"> begin() </font><font size="3">must
point to the first </font><font size="2" face="Courier New">DataObj</font><font
size="3"> in the view and </font><font size="2" face="Courier">end()
</font><font size="3">to one past the last </font><font size="2"
face="Courier New">DataObj </font><font size="3">in the view. To
provide this conceptual behavior, the dereferencing operators
must be able to grab the first record from the database if the
iterator hasn't done so already. So the </font><font size="2"
face="Courier New">ReadData() </font><font size="3">function in
the above example code will say its reading elements 0, 2, 3, 4,
etc., rather than the 1, 2, 3, 4, etc., you would expect. This
behavior occurs as the following happens:</font></p>
<ul>
<li><font size="3">The program enters the first time through
the loop. The iterator hasn't needed to access the
database, so no elements have been read yet. Thus </font><font
size="2" face="Courier New">GetLastCount() == 0. </font><font
size="3">Thus, the program prints </font><font size="2"
face="Courier New">"Reading element #0".</font></li>
<li><font size="2" face="Courier New">operator*() </font><font
size="3">executes, reading the first </font><font
size="2" face="Courier New">DataObj </font><font size="3">from
the database. So far then, the iterator has grabbed one </font><font
size="2" face="Courier New">DataObj </font><font size="3">so
far.</font></li>
<li><font size="3">Then, after the next few statements work
with the fetched </font><font size="2" face="Courier New">DataObj,
</font><font size="3">the program prepares for the next
iteration of the loop by incrementing</font><font
size="2"> </font><font size="3">the</font><font size="2">
</font><font size="2" face="Courier New">select_iterator</font><font
size="3">, thus fetching another </font><font size="2"
face="Courier New">DataObj. </font><font size="3">Now two</font><font
size="2" face="Courier New"> DataObj's </font><font
size="3">have been read and the next invocation of</font><font
size="2" face="Courier New"> GetLastCount() </font><font
size="3">returns</font><font size="2" face="Courier New">
2. </font><font size="3">The program now displays </font><font
size="2" face="Courier New">"Reading element
#2".</font></li>
<li><font size="3">From there in this and all future
iterations of the loop:</font><font size="2"
face="Courier New"> operator*() </font><font size="3">just
returns the value of the already fetched </font><font
size="2" face="Courier New">DataObj. </font><font
size="3">It does not read another </font><font size="2"
face="Courier New">DataObj </font><font size="3">at all
from the database. Only one object will be read overall
per iteration in the loop, that done by </font><font
size="2" face="Courier New">operator++().</font></li>
</ul>
<h3>See also</h3>
<p><a href="db_iterator.htm"><font size="2" face="Courier New">DB_iterator</font></a>,
<a href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a>, <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input
Iterator</a>.<br>
<br>
</p>
<hr>
<p><a href="index.htm"><img src="dtl_home.gif" alt="[DTL Home]"
width="54" height="54"></a> <br>
</p>
<p>Copyright
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -