Re: STL (boost) and copies of iterator
On 3 Mai, 23:13, Thomas Mang <noth...@provided.com> wrote:
Daniel Kr?gler wrote:
On 3 Mai, 15:55, Thomas Mang <noth...@provided.com> wrote:
For the case in question it's irrelevant that the algorithm can hardly
do anything - the issue is after the call to the algorithm the number of
iterators existing must be the same number as before ("within" the
algorithm, the number does not matter). So if it just keeps a copy
that's enough to break the logic (the logic which I question because of
the implications it has).
If you have followed my argumentation (and have no fault found ;-))
then you should come to the same conclusion as I, namely that
an algorithm *cannot* store any argument iterator in a static
variable. Doing this, at least *destruction* of the static variable
would always take place (you cannot prevent it) and this could
not generally safely done.
But just in that moment where I say this, I found a trick that
invalidates my above conclusion and would be a *real*
lawyer's solution: Use the free store and never free it:
template <typename Iter>
void algorithm(Iter it) {
static Iter* pi = new Iter(it); // Just for fun..
}
Result: A copy is made and is never accessed any more,
no destructor involved.
Great. Genious. Let's give that algorithm a cool name. What
about "memleak"? (At least, if we call it for arbitrary different
iterator types in one program, otherwise it's a finite number of
allocations).
Well, by as-if the compiler can find out that the container will exist
for a long, long time. If it stores iterators during that time and
destroys it before the container fades away but after the call to the
algorithm has been finished (and the next couple of statements executed)
the logic is screwed again.
I cannot follow your argumentation here. What has the as-if
rule to do with the problem? Probably I have not understood
your actual problem, but I cannot see how you write one of the
algorithms of the standard library such that the function
recognizes (via magic?) that it can assume that the backing
sequence of the given iterators life's long enough to be valid
in the static c'tor - which means until the end of the program.
How do you solve the following feasible invocation of std::copy:
#include <algorithm>
#include <vector>
#include <set>
#include <iterator>
void foo() {
std::set<int> s;
{ // local scope starts
std::vector<int> v = ...; // Some initialized
std::copy(v.begin(), v.end(), std::inserter(s,
s.begin()));
} // local scope ends (*)
// ... more stuff with s
}
How can your implementation of std::copy know,
that its static local variable must destroy it's copy
of e.g. v.begin() before (*)?
Does the Standard explicitly rule out that at the end of the call to an
algorithm all iterators passed in as parameters as well as internal
copies of those iterators will be destroyed again?
IMO there exists no such explicit rule. But - honestly - I
never searched for it.
If not, was that intended or an oversight?
I don't know. The standard is not required to specify
an explicit rule for every thinkable situation. In this
case I would take the pragmatic point of view, that
we can *implicitely* exclude the validity of a non-pointer
local static holding a copy of it's arguments. It
seems to be possible to do so with either a pointer
of free store as described above or by an explicit
invocation of the d'tor at any point before the end of
the function call (in the very last situation it is necessary
that the local static is actually a char array of sufficient
size interpreted as iterator type and explicit in-memory
construction and explicit d'tor invocation is also needed).
Any *normal* implementation doing such things is
probably insane, but one could think of some
instrumentation techniques that would do this kind of stuff.
Furthermore, regarding your destructor issue: Is it 24.1/5 that
expresses this?
No, it is not.
If yes, I wonder if the example can be correct, because
an uninitialized pointer can not only be assigned a new value, but can
also be destroyed.
The example is correct, because the d'tor of a pointer effectively
is a noop, see 5.2.4/1.
So where does it state (explicitly or implicitly) that the destruction
of an iterator requires it to be of non-singular value (or that the
container it belongs to is still in a valid state etc.)?
There is no explicit statement concerning this (AFAIK),
but I cannot see that an implementation of an iterator,
which saves a reference to it's container and which
somehow accesses the referenced container (if not default
constructed) inside it's d'tor must necessarily violate the
requirements of an iterator. Can you proof the contrary?
As an example, I can think of a container that contains
an member of integral type as a counter of living and
referencing iterators. Each iterator could decrease this
counter inside its d'tor to complete the statistics (and
increase the counter in its c'tors).
Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]