C++ iterate an array of integers whose size is unknown? - c++

I have the following array:
int* myArray = new int[45];
If I wanted to iterate each element without knowing the actual size of the array, I would need to use a for_each?
If so, then how would you write the for_each? I was looking over the following site and reading up on for_each but can't figure out how to put this together.
http://www.cplusplus.com/reference/algorithm/for_each/
Update: A for_each is not a good choice in this case, due to the fact that the size of the array has to be known. vectors are the proper way to accomplish such task. My reason for using arrays, in this case, was for learning purposes. if this was a serious project I would move to something such as Lists/Vectors.

Note when the question was first posted, the array in question was declared as
int myArray[45];
This answer deals with that particular case.
If you have C++11 support, you can use a range based loop:
for (int& i : myArray) {
std::cout << i << "\n";
}
C++11 also provides std::begin and std::end, which you can use with a fixed size array to obtain iterators:
std::for_each(std::begin(myArray), std::end(myArray), <func>);
Another option, which works for C++03 and you are dealing with fixed size arrays, is to define a function template:
// taken a fixed size array by reference and loop over it
template <typename T, unsigned int N>
void array_for_each( T (&a)[N]) {
for (unsigned int i = 0; i < N; ++i) {
// do something with array elements
std::cout << a[i] << " ";
}
}
int main() {
int a[5];
array_for_each(a);
}

If you use MSVC (Microsoft Visual C++), you can use "for each."
for each(int i in arr) {
cout << i << ' ' << endl;
}
NOTE: This only works in the block of code the array is declared in.
If not, you can also use the new range-based for loop in the C++11 standard.
for(int i : arr) {
cout << i << ' ' << endl;
}
If you're intent upon the std::for_each:
for_each(arr,arr + 10,[] (int i) {
cout << i << ' ' << endl;
});
NOTE: This requires knowledge of the size of the array (in this example, 10).

You could use a for_each. In this case, you have allocated space for 45 elements in your array, but since it is NULL, you'd probably get a segfault if you tried to do anything. You either need to hold a value of the array, or use something like sizeof(myArray)/sizeof(myArray[0]) (which has its own problems).
Anyway, for a for_each here, if we actually had 45 elements:
std::for_each(myArray, myArray + 45, <func>);
Anyway, this is part of the reason to use vectors: .begin() and .end() reduces errors with using incorrect indexing.

You have described an array of int, not a class that implements a InputIterator, which is what the for_each is designed for, even though you can use it to iterate an array, but you need to know the size of the array to iterate it.
If you want to use for_each you need to use a vector, list, or implement a class that keeps track of the number of elements it contains. IMO it is much easier to just use a vector
If you want to just iterate your current array, assuming it is 0 terminated:
for(int *value = myArray; *value != 0; ++value)
printf("%d\n", *value);
Or, you can use indexes:
for(int index = 0; myArray[index] != 0; ++index)
printf("%d\n", myArray[index]);
IMO the pointer method is cleaner.
This code is still dangerous though, you should either keep track of the number of records in a seperate variable, or use a vector.

Related

Why does sizeof(ar)/ sizeof(ar[0]) not work properly on a vector when passed to a function?

I'm trying to get to know c++ better and came across this confusion.
int simpleArraySum(const vector<int> ar) {
int n=sizeof(ar)/sizeof(ar[0]);
int sum=0;
for (int i=0; i<n; i++){
sum+=ar[i];
}
return sum;
}
When I passed a vector of 10 elements the result was lower than expected. I checked that n=6 unlike when I use size() which gives n=10. My confusion comes since the way the code is written works normally in main with sizeof(ar)/sizeof(ar[0]).
Using the "sizeof trick" have never worked on a std::vector.
The size of a std::vector object is the size of the std::vector object itself, not the possible data handled by the vector.
If you want to get the number of elements from a std::vector object, use the size member function.
The "sizeof trick" only works on actual arrays, like e.g.
int array[10];
std::cout << sizeof(array) / sizeof(array[0]) << '\n'; // Will print 10
As for the problem you try to solve with your function, there are much better ways to handle it.
First you could iterate using the size (like you do now)
for (size_t i = 0; i < ar.size(); ++i)
sum += ar[i];
Then you could iterate using iterators
for (auto i = ar.begin(); i != ar.end(); ++i)
sum += *i;
Then you have range-based for loops
for (auto value : ar)
sum += value;
Lastly you can use a standard algorithm function like std::accumulate
int simpleArraySum(std::vector<int> const& ar)
{
return std::accumulate(begin(ar), end(ar), 0);
}
Why does sizeof(ar)/ sizeof(ar[0]) not work properly on a vector ...
sizeof(ar)/ sizeof(ar[0]) is an expression that gives you the length of an array, and only an array. std::vector is not an array. std::vector is a class (template).sizeof(std::vector) is entirely unrelated to the number of elements it has i.e. its length.
The size of all types is compile time constant. std::vector's can contain a variable number of elements that is not compile time constant. Therefore the size of vector type cannot depend on the number of elements.
... when passed to a function?
It won't work when not passing into a function either.

Is there a way to make this code faster?

I have a C++ struct that I need to convert to a list so that I can load into GPU
struct point_cloud_tensor
{
std::vector<float> timestamp;
std::vector<std::vector<double>> position;
// more fields
};
point_cloud_tensor sweep_to_array(const point_sweep &point_sweep)
{
const auto num_points = point_sweep.points.size();
point_cloud_tensor tensor;
point_cloud_tensor.timestamp.reserve(num_points);
point_cloud_tensor.point.reserve(num_points);
for (int i = 0; i < point_sweep.points.size(); i++)
{
const auto point = point_sweep.points.at(i);
tensor.timestamp.push_back(point.timestamp);
std::vector<double> point_triple(3);
point_triple.push_back(point.x);
point_triple.push_back(point.y);
point_triple.push_back(point.z);
tensor.position.push_back(point_triple);
// more fields
}
return tensor;
}
There are about 100K points in the sweep vector and this runs in about 30ms.
Is there a way to substantially reduce this?
In this case, your std::vector is being used for a small sized array, for this you can replace it by std:array
As mentioned, testing how fast a code can be run, is a matter of hardware so I can't be 100% sure if it is faster with this change.
Do not call size() every time if it does not change
Since you already store point_sweep.points.size() into the variable num_points, you can use it in your for loop. When you iterate like that:
for (int i = 0; i < point_sweep.points.size(); i++)
Every iteration you will dereference point_sweep and dereference points to call its method size(). It should be faster to use the local variable instead:
for (int i = 0; i < num_points; i++)
Use a reference when appropriate
When you fetch your point:
const auto point = point_sweep.points.at(i);
You are calling the copy constructor for no reason. You should use a reference to it, using &:
const auto& point = point_sweep.points.at(i);
References can be risky because every modification you perform will be applied to the original object, but since you are using a const reference, you should be safe.
Minimize the calls when pushing elements to the back of a vector
When you fill up your tensor.position vector, you may:
Create the point with an intializer_list
Add the item without a temporary variable, in order to be move-able
So, this code:
std::vector<double> point_triple(3);
point_triple.push_back(point.x);
point_triple.push_back(point.y);
point_triple.push_back(point.z);
tensor.position.push_back(point_triple);
Becomes:
tensor.position.push_back({point.x, point.y, point.z});
Plus it becomes easier to read, in my opinion.
Use another 3D point structure (if possible)
Also, as others have pointed out, if you can change the data structures then you may use an std::array or std::tuple or you may simply write a struct such as struct Point { double x, y, z; }. The array can be accessed almost exactly like a vector, which should make the transition a bit easier. The tuple must be accessed by std::get which needs to rewrite a bit of code. For example if you want to display the contents of the last element:
struct point_cloud_tensor
{
std::vector<float> timestamp;
std::vector<std::tuple<double,double,double>> position;
// more fields
} tensor;
auto last_pos = tensor.position.back();
std::cout << "x=" << std::get<0>(last_pos) << ' ';
std::cout << "y=" << std::get<1>(last_pos) << ' ';
std::cout << "z=" << std::get<2>(last_pos) << std::endl;
However, with tuples you can add items with emplace_back instead of push_back, which saves you a move constructor, e.g.:
tensor.position.emplace_back(point.x, point.y, point.z);
Notice the difference in syntax. With push_back you have one parameter {point.x, point.y, point.z} but with emplace_back you have 3 parameters point.x, point.y, point.z. Basically with emplace_back you are just removing the curly braces.
Did you thought about making step backward and creating a list when constructing points?

Apply std::begin() on an dynamically allocated array in a unique_ptr?

I have an unique pointer on a dynamically allocated array like this:
const int quantity = 6;
unique_ptr<int[]> numbers(new int[quantity]);
This should be correct so far (I think, the [] in the template parameter is important, right?).
By the way: Is it possible to initialize the elements like in int some_array[quantity] = {}; here?
Now I was trying to iterate over the array like this:
for (auto it = begin(numbers); it != end(numbers); ++it)
cout << *it << endl;
But I cannot figure out, how the syntax is right. Is there a way?
Alternatively I can use the index like:
for (int i = 0; i < quantity; ++i)
cout << numbers[i] << endl;
Is one of these to be preferred?
(Not directly related to the title: As a next step I would like to reduce that to a range-based for loop but I just have VS2010 right now and cannot try that. But would there be something I have to take care of?)
Thank you! Gerrit
Compiler is supposed to apply this prototype for std::begin:
template< class T, size_t N >
T* begin( T (&array)[N] );
It means the parameter type is int(&)[N], neither std::unique_ptr nor int *. If this is possible, how could std::end to calculate the last one?
But why not use raw pointer directly or a STL container?
const int quantity = 6;
std::unique_ptr<int[]> numbers{new int[quantity]};
// assignment
std::copy_n(numbers.get(), quantity,
std::ostream_iterator<int>(std::cout, "\n"));
const int quantity = 6;
std::vector<int> numbers(quantity, 0);
// assignment
std::copy(cbegin(numbers), cend(numbers),
std::ostream_iterator<int>(std::cout, "\n"));
Dynamically allocated arrays in C++ (ie: the result of new []) do not have sizing information. Therefore, you can't get the size of the array.
You could implement std::begin like this:
namespace std
{
template<typename T> T* begin(const std::unique_ptr<T[]> ptr) {return ptr.get();}
}
But there's no way to implement end.
Have you considered using std::vector? With move support, it shouldn't be any more expensive than a unique_ptr to an array.

How does the range-based for work for plain arrays?

In C++11 you can use a range-based for, which acts as the foreach of other languages. It works even with plain C arrays:
int numbers[] = { 1, 2, 3, 4, 5 };
for (int& n : numbers) {
n *= 2;
}
How does it know when to stop? Does it only work with static arrays that have been declared in the same scope the for is used in? How would you use this for with dynamic arrays?
It works for any expression whose type is an array. For example:
int (*arraypointer)[4] = new int[1][4]{{1, 2, 3, 4}};
for(int &n : *arraypointer)
n *= 2;
delete [] arraypointer;
For a more detailed explanation, if the type of the expression passed to the right of : is an array type, then the loop iterates from ptr to ptr + size (ptr pointing to the first element of the array, size being the element count of the array).
This is in contrast to user defined types, which work by looking up begin and end as members if you pass a class object or (if there is no members called that way) non-member functions. Those functions will yield the begin and end iterators (pointing to directly after the last element and the begin of the sequence respectively).
This question clears up why that difference exists.
I think that the most important part of this question is, how C++ knows what the size of an array is (at least I wanted to know it when I found this question).
C++ knows the size of an array, because it's a part of the array's definition - it's the type of the variable. A compiler has to know the type.
Since C++11 std::extent can be used to obtain the size of an array:
int size1{ std::extent< char[5] >::value };
std::cout << "Array size: " << size1 << std::endl;
Of course, this doesn't make much sense, because you have to explicitly provide the size in the first line, which you then obtain in the second line. But you can also use decltype and then it gets more interesting:
char v[] { 'A', 'B', 'C', 'D' };
int size2{ std::extent< decltype(v) >::value };
std::cout << "Array size: " << size2 << std::endl;
According to the latest C++ Working Draft (n3376) the ranged for statement is equivalent to the following:
{
auto && __range = range-init;
for (auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin) {
for-range-declaration = *__begin;
statement
}
}
So it knows how to stop the same way a regular for loop using iterators does.
I think you may be looking for something like the following to provide a way to use the above syntax with arrays which consist of only a pointer and size (dynamic arrays):
template <typename T>
class Range
{
public:
Range(T* collection, size_t size) :
mCollection(collection), mSize(size)
{
}
T* begin() { return &mCollection[0]; }
T* end () { return &mCollection[mSize]; }
private:
T* mCollection;
size_t mSize;
};
This class template can then be used to create a range, over which you can iterate using the new ranged for syntax. I am using this to run through all animation objects in a scene which is imported using a library that only returns a pointer to an array and a size as separate values.
for ( auto pAnimation : Range<aiAnimation*>(pScene->mAnimations, pScene->mNumAnimations) )
{
// Do something with each pAnimation instance here
}
This syntax is, in my opinion, much clearer than what you would get using std::for_each or a plain for loop.
It knows when to stop because it knows the bounds of static arrays.
I'm not sure what do you mean by "dynamic arrays", in any case, if not iterating over static arrays, informally, the compiler looks up the names begin and end in the scope of the class of the object you iterate over, or looks up for begin(range) and end(range) using argument-dependent lookup and uses them as iterators.
For more information, in the C++11 standard (or public draft thereof), "6.5.4 The range-based for statement", pg.145
How does the range-based for work for plain arrays?
Is that to read as, "Tell me what a ranged-for does (with arrays)?"
I'll answer assuming that - Take the following example using nested arrays:
int ia[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
for (auto &pl : ia)
Text version:
ia is an array of arrays ("nested array"), containing [3] arrays, with each containing [4] values. The above example loops through ia by it's primary 'range' ([3]), and therefore loops [3] times. Each loop produces one of ia's [3] primary values starting from the first and ending with the last - An array containing [4] values.
First loop: pl equals {1,2,3,4} - An array
Second loop: pl equals {5,6,7,8} - An array
Third loop: pl equals {9,10,11,12} - An array
Before we explain the process, here are some friendly reminders about arrays:
Arrays are interpreted as pointers to their first value - Using an array without any iteration returns the address of the first value
pl must be a reference because we cannot copy arrays
With arrays, when you add a number to the array object itself, it advances forward that many times and 'points' to the equivalent entry - If n is the number in question, then ia[n] is the same as *(ia+n) (We're dereferencing the address that's n entries forward), and ia+n is the same as &ia[n] (We're getting the address of the that entry in the array).
Here's what's going on:
On each loop, pl is set as a reference to ia[n], with n equaling the current loop count starting from 0. So, pl is ia[0] on the first round, on the second it's ia[1], and so on. It retrieves the value via iteration.
The loop goes on so long as ia+n is less than end(ia).
...And that's about it.
It's really just a simplified way to write this:
int ia[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
for (int n = 0; n != 3; ++n)
auto &pl = ia[n];
If your array isn't nested, then this process becomes a bit simpler in that a reference is not needed, because the iterated value isn't an array but rather a 'normal' value:
int ib[3] = {1,2,3};
// short
for (auto pl : ib)
cout << pl;
// long
for (int n = 0; n != 3; ++n)
cout << ib[n];
Some additional information
What if we didn't want to use the auto keyword when creating pl? What would that look like?
In the following example, pl refers to an array of four integers. On each loop pl is given the value ia[n]:
int ia[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
for (int (&pl)[4] : ia)
And... That's how it works, with additional information to brush away any confusion. It's just a 'shorthand' for loop that automatically counts for you, but lacks a way to retrieve the current loop without doing it manually.
Some sample code to demonstrate the difference between arrays on Stack vs arrays on Heap
/**
* Question: Can we use range based for built-in arrays
* Answer: Maybe
* 1) Yes, when array is on the Stack
* 2) No, when array is the Heap
* 3) Yes, When the array is on the Stack,
* but the array elements are on the HEAP
*/
void testStackHeapArrays() {
int Size = 5;
Square StackSquares[Size]; // 5 Square's on Stack
int StackInts[Size]; // 5 int's on Stack
// auto is Square, passed as constant reference
for (const auto &Sq : StackSquares)
cout << "StackSquare has length " << Sq.getLength() << endl;
// auto is int, passed as constant reference
// the int values are whatever is in memory!!!
for (const auto &I : StackInts)
cout << "StackInts value is " << I << endl;
// Better version would be: auto HeapSquares = new Square[Size];
Square *HeapSquares = new Square[Size]; // 5 Square's on Heap
int *HeapInts = new int[Size]; // 5 int's on Heap
// does not compile,
// *HeapSquares is a pointer to the start of a memory location,
// compiler cannot know how many Square's it has
// for (auto &Sq : HeapSquares)
// cout << "HeapSquare has length " << Sq.getLength() << endl;
// does not compile, same reason as above
// for (const auto &I : HeapInts)
// cout << "HeapInts value is " << I << endl;
// Create 3 Square objects on the Heap
// Create an array of size-3 on the Stack with Square pointers
// size of array is known to compiler
Square *HeapSquares2[]{new Square(23), new Square(57), new Square(99)};
// auto is Square*, passed as constant reference
for (const auto &Sq : HeapSquares2)
cout << "HeapSquare2 has length " << Sq->getLength() << endl;
// Create 3 int objects on the Heap
// Create an array of size-3 on the Stack with int pointers
// size of array is known to compiler
int *HeapInts2[]{new int(23), new int(57), new int(99)};
// auto is int*, passed as constant reference
for (const auto &I : HeapInts2)
cout << "HeapInts2 has value " << *I << endl;
delete[] HeapSquares;
delete[] HeapInts;
for (const auto &Sq : HeapSquares2) delete Sq;
for (const auto &I : HeapInts2) delete I;
// cannot delete HeapSquares2 or HeapInts2 since those arrays are on Stack
}

Passing a list of numbers to a function in C++ without building array first?

I'm trying to build a function that accepts an array in the following manner:
int inCommon = findCommon({54,56,2,10}, 4);
int findCommon(int nums[], int len){
for(int i=0; i<len; i++) cout<<nums[i]<<endl;
return 1;
}
Note, that's not actually what my function does, but I do loop through the array. I'm just trying to determine if it's possible to pass an array like {54,56,2,10} instead of having to create an array and pass it? (like this:
int theArray[]= {54,56,2,10};
int inCommon = findCommon(theArray,4);
This is not possible at the time. However, in the next C++ standard C++0x, this will be done using initalizer lists:
int findCommon(std::initializer_list<int> nums)
{
std::initializer_list<int>::iterator it;
for (it = nums.begin() ; it != nums.end() ; ++it)
{
std::cout << *it << std::endl;
}
return 1;
}
See this presentation from Bjarne Stroustrup, and this article from Wikipedia
If you want to try C++0x features, you can check the last versions of gcc, that supports some of them.
You need C++0x!
http://en.wikipedia.org/wiki/C%2B%2B0x#Initializer_lists
No, I believe {} may only be used to initialize an array.
You can do what you want to do using variable argument lists.
no. It is impossible.
But you can create something like template T* arrayCreator(...) function which will create your array,
Or array wrapper with constructor with unspecified arguments count.
Or create object which will have overloaded operator coma or << and will create your array, findCommon( arrCreator() << 1 << 2 << 3 << 5, other parammeters ) - this method more type safe
Or waiting C++0x implementation.