Question

I got an assignment to implement a template array with an iterator and to overlad some operators of my iterator and I have a few questions. From what i understand the std random accessed iterator allows u to exceed the array. Does it allow to get the value it is holding over the Size? Does it allow the user to write over that memory?

And for my implementation, should i allow access over the Size? should i allow to get the data out of the Size? should i allow any change to it?

what is considered good programming in this case?

any help will be much appreciated

Was it helpful?

Solution 2

I think you may be reading too much into your assignment, but your questions do bear consideration nonetheless.

First of all, some considerations:

  • there are both mutating and non-mutating iterators (iterator and const_iterator nested types in general), the former allowing writing to the pointed-to element, and the latter not.
  • iterators are supposed to be lightweight, they are copied over and over in many algorithms

Now, with regard to your questions, there is indeed a design decision on whether to perform bounds checking or not.

In general, iterators in C++ are so lightweight that they perform no bounds checking at all. This is the name of efficiency and the you don't pay for what you don't use philosophy. If the user ever overshoot... she will fall prey to Undefined Behavior, that is anything could happen.

However, most (if not all) STL implementations will also acknowledge the issue and provide a debug mode (checked mode) that you can use when testing your application; of course those induce an additional cost, not only CPU-wise but also potentially memory-wise.

As such, it is your own choice whether to provide checks, or not, and possibly to provide it optionally. I would recommend starting off without checks, and only tack them on later on as you have a better idea of what the system looks like.

OTHER TIPS

The amount of runtime checking that iterators do is up to them. The std library iterators generally do very little runtime checking, as part of the design philosophy of the std library is to give near-hand-coded container performance with high level type checking.

However, many std library implementations include multiple levels of runtime checking as an option for debug builds. This means that if you ask for the contents of an invalid iterator, the std iterator will invoke undefined behavior and probably give you the contents of some random memory past the end of the buffer, or sometimes segfault. And if you write, it will happily write to that memory that you aren't allowed to write to.

As you are writing an iterator, it would be a good idea to include debugging tools within the iterator, because you won't write it correctly the first time. While std library iterator debugging tools are mainly about catching the user of the iterator making a mistake, the kind of checks you'll want to do to determine if the writer of the iterator is making a mistake (ie, you) would be similar.

It would be good practice to both include, and to not include, such checks. And you should definitely include such checks (hooked up to an exception, assert, or even just an error logging system -- cerr counts as error logging in this context) when developing your iterators, even if the checks can be disabled or go away in "production" code.

The size is not important for overflow. A random access iterator means that you can lookup an element with operator[] or increment or decrement by an arbitrary amount with operator += or + or -= or -

View all the operations needed here http://www.cplusplus.com/reference/iterator/RandomAccessIterator/

In the Standard C++ Library (formerly known as STL) iterators do not perform range checking in the same way that in C pointers do not perform range checking. Accessing memory through an iterator pointing beyond the allocated bounds is undefined behavior, in the same way that accessing memory through a pointer that points beyond the allocated bounds is undefined behavior. You should follow the same principle in the design of your iterators, i.e. you should perform no bounds checks on data accesses.

From what i understand the std random accessed iterator allows u to exceed the array.

Not quite; you can't access anything outside the container, and trying to do so will give undefined behaviour. But the iterator is not required to prevent you from trying to access invalid memory.

The reason is that there could be a significant runtime cost to checking the range; by not requiring this, you can have the choice between a fast implementation that requires you to design your access patterns correctly, or a slow, safer implementation that can detect some mistakes for you.

Does it allow to get the value it is holding over the Size? Does it allow the user to write over that memory?

It might detect that and report an error; or it might not, and allow you to access invalid memory with undefined results.

And for my implementation, should i allow access over the Size?

No, it makes no sense to allow it. You can choose whether to actively prevent it by checking access at runtime, or to passively prevent it by documenting that it's the user's responsibility to make sure the iterator remains valid.

what is considered good programming in this case?

An unchecked iterator is simpler and doesn't add any, perhaps unwanted, performance costs. You could provide checked iterators as well; either separately or as wrappers around the unchecked ones, to give the user the choice of how fast or safe they want it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top