Is an Iterator in C++ a Pointer

Is it safe to iterate a pointer to the next blob of data in C?

Is it then true or false to assume that iterating the pointer to any of those structs as a struct Header pointer will result in the address of the next member of that struct?

It is not safe to make such an assumption. C implementations are allowed to put arbitrary amounts of padding between struct members (in a manner that is consistent for any given struct type). Thus, roughly speaking, your function could produce a pointer to padding, rather than a pointer to the member following the header.

And how do the C data alignment requirements come and play in such scenarios? (Can eventual slop lead to bad pointers when casting for example?)

C implementations typically use alignment requirements in determining how much padding, if any, to insert between members, but the standard does not require them to do so, nor in general does it constrain how implementations make that decision.

How to check whether iterators form a contiguous memory zone?

Leaving aside your sample function, you can never be completely sure that iterators will form a contiguous memory without checking the address of every element between the two.

A reasonable sanity test, though, would be to just check if the memory area between the two is the same as the count between the two:

assert(&*last - &*first == last - first &&
"Iterators must represent a contiguous memory region");

int pointer to the .end() of a list

To implement begin() and end() in a style similar to STL return iterators, not pointers:

template <typename value_type>
class my_list
{
public:
typedef std::list<value_type>::iterator iterator;
typedef std::list<value_type>::const_iterator const_iterator;

iterator begin() { return listofValues.begin(); }
const_iterator begin() const { return listofValues.begin(); }

iterator end() { return listofValues.end(); }
const_iterator end() const { return listofValues.end(); }
};

Using other methods on a structure inside a `for` loop over an iterator which can mutate this structure

This is possibly bug #8372 caused by the minimum-that-works implementation of the current for. It is implemented as a macro such that

for pattern in iterator { body }

expands to (you can see this by running rustc --pretty expanded foo.rs)

{
let it = &mut iterator;
loop {
match it.next() {
None => break,
Some(pattern) => { body }
}
}
}

The problem is the &mut iterator borrow, which stops iterator being used directly while it is in scope. You can normally work around this by manually writing the expansion yourself:

impl<'a> SomeTrait for &'a mut SomeStructure<'a> {
fn do_something(self) {
let mut it = self.iter();
loop {
match it.next() {
None => break
Some(e) => {
if self.test_something() {
break;
}
}
}
}
}
}

That said... this may not actually work in this case if self.iter() borrows self (especially if test_something takes &mut self, since the compiler has to disallow mutation or the iterator could be invalidated).

If you were to add a .view_creator() method to the return of self.iter() (assuming you have a reference to self in the self.iter() type) then it.view_creator().test_something() would work (with the manually unwrapped for loop).

(FWIW, it's a little peculiar to have a trait taking self and implementing it on &mut Thing rather than taking &mut self and implementing it straight on Thing; although there are good reasons for it sometimes.)

How are random access iterators for non-contiguous containers (such as std::deque) implemented?

You can satisfy the requirememts of a std::deque with a std::vector<std::unique_ptr<std::array<T,N>>> roughly. plus a low/high water mark telling you where the first/last elements are. (for an implementation defined N that could vary with T, and the std::arrays are actually blocks of properly aligned uninitialized memory and not std::arrays, but you get the idea).

Use usual exponential growth, but on both front and back.

Lookup simply does (index+first)/N and %N to find the block and sub element.

This is more expensive than a std::vector lookup, but is O(1).

what is the difference between const_iterator and iterator?

There is no performance difference.

A const_iterator is an iterator that points to const value (like a const T* pointer); dereferencing it returns a reference to a constant value (const T&) and prevents modification of the referenced value: it enforces const-correctness.

When you have a const reference to the container, you can only get a const_iterator.

Edited: I mentionned “The const_iterator returns constant pointers” which is not accurate, thanks to Brandon for pointing it out.

Edit: For COW objects, getting a non-const iterator (or dereferencing it) will probably trigger the copy. (Some obsolete and now disallowed implementations of std::string use COW.)

Printing the value of an int Pointer

One problem is likely to be this line:

pointerlist.push_back((&*listOfValues.begin() + endptr));

Your listOfValues is a std::list, and therefore its values are not stored in a contiguous block of memory. So you're getting an iterator to the first element with listOfValues.begin(), dereferencing the iterator with *, taking the address of that with & to get an int*, then adding some value which points somewhere off into memory that you don't know what it is.

Try doing this instead:

pointerlist.push_back((&*(listOfValues.begin() + endptr)));

where you add endptr to the iterator (to advance it along the list), then dereference and take the address. Actually you may need to use advance instead of +.

How do function pointers in C work?

Function pointers in C

Let's start with a basic function which we will be pointing to:

int addInt(int n, int m) {
return n+m;
}

First thing, let's define a pointer to a function which receives 2 ints and returns an int:

int (*functionPtr)(int,int);

Now we can safely point to our function:

functionPtr = &addInt;

Now that we have a pointer to the function, let's use it:

int sum = (*functionPtr)(2, 3); // sum == 5

Passing the pointer to another function is basically the same:

int add2to3(int (*functionPtr)(int, int)) {
return (*functionPtr)(2, 3);
}

We can use function pointers in return values as well (try to keep up, it gets messy):

// this is a function called functionFactory which receives parameter n
// and returns a pointer to another function which receives two ints
// and it returns another int
int (*functionFactory(int n))(int, int) {
printf("Got parameter %d", n);
int (*functionPtr)(int,int) = &addInt;
return functionPtr;
}

But it's much nicer to use a typedef:

typedef int (*myFuncDef)(int, int);
// note that the typedef name is indeed myFuncDef

myFuncDef functionFactory(int n) {
printf("Got parameter %d", n);
myFuncDef functionPtr = &addInt;
return functionPtr;
}

Is vector in c++ a pointer?

Is vector in c++ a pointer?

No. std::vector is not a pointer. It is a class.

So is v a pointer that points to the start of the vector?

No, but v (an instance of the vector class) does happen to contain a pointer to the start of the array.

why can't I access *v?

Because there is no overload for the unary operator* for the class std::vector.



Related Topics



Leave a reply



Submit