3

Whenever I iterate over a C++ array by pointer arithmetics (i.e. not with Java-style incrementing of an index), I first get the address of the last element in the array and then iterate as long as the current address is not the last address:

#include <iostream> using namespace std; int main() { int values[] = { 1, 2, 3, 4, 5 }; int* lastAddress = values + size(values); for (int *p=values; p != lastAddress; p++) { cout << "val: " << *p << endl; } } 

Is this the generally accepted way of doing this kind of thing?

14
  • 2
    No, the "generally accepted" way is to use C++11's range iteration, to do all of this for you. This is the legacy way of working with arrays. C++11 is almost ten years old, and offers more convenient ways of doing many things of this nature. Commented Sep 26, 2020 at 13:27
  • 1
    Does this answer your question? C++11 range based loop: How does it really work Commented Sep 26, 2020 at 13:33
  • 1
    for (auto p = begin(values); p != end(values); ++p) , the for loop can be replaced like this too. Commented Sep 26, 2020 at 13:33
  • 1
    Guys, don't answer in the comments. Thanks. Commented Sep 26, 2020 at 13:49
  • 1
    @TMOTTM std::begin / std::end don't return pointers. They return iterators. Commented Sep 26, 2020 at 13:51

2 Answers 2

5

You can use a range based for loop. Like so:

for (const auto val : values) { std::cout << "Val: " << val << '\n'; } 

Note the use of \n rather than std::endl. std::endl implies a std::flush of the stream and you probably don't need that after every line. You can do one after the loop if needed.

Sign up to request clarification or add additional context in comments.

8 Comments

Note: this assumes that values is std::array or std::vector, not a simple C array as in question. But it is in general not a good idea to use simple C arrays in C++.
@Wolfram works for C arrays too. godbolt.org/z/rq3jxb
@Wolfram Nope. Native arrays are fine.
Better improve and maybe drop an explanatory note. As you did for the abominable using namespace, though dropping a note would be nice.
@Wolfram While it's true that std::array can often be preferred to C arrays, that has nothing to do with anything in the question, for which ranged-based for, std::begin and std::end are all perfectly fine as-is. The dimension is part of the type, and that's how they work. :)
|
4

Is this the generally accepted way of doing this kind of thing?

No, it isn't. You shouldn't do hand made pointer arithmetics for determining start and end of a container. That's what std::begin() and std::end() are for:

#include <iostream> using namespace std; int main() { int values[] = { 1, 2, 3, 4, 5 }; for (auto p = std::begin(values); p != std::end(values); p++) { cout << "val: " << *p << endl; } } 

As a short form you can use a range based for loop, which uses the same mechanism under the hood:

for(auto value : values) { cout << "val: " << value << endl; }; 

Please note, that this only works with arrays declared locally with a well known size (sizeof()).

If you get such array definitions passed to a function, you still also need to pass the size:

 foo(int values[], size_t size) { for(auto val = std::begin(values); p != std::begin(values) + size; ++p) { // ... } } 

The standard accepted way is to ditch raw arrays at all, in favor of using std::array<T,N> for arrays of known size, or std::vector<T> for arrays of unknown size.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.