Given a vector of ints I saw my professor writing:
for (int i=0;i<vect.size();++i)
{
}
I argue that his code isn't efficient and could be replaced by the following, am I right?
int vect_size=vect.size();
for (int i=0;i<vect_size;++i)
{
}
Don't fall into premature optimization traps like this. Your compiler is more than capable of optimize those lines if needed (and if instructed).
There are other things that you should note.
Assuming that vect is a vector, std::vector::size() returns a size_t value, which is an unsigned type. Your compiler may warn you about the comparison i < vect.size() which involves variables of different signedness.
If you really want i to be an int (there may be no reasons for it to be unsigned) you can use the following
for ( int i = 0, v_size = vect.size(); i < v_size; ++i ) { /* ... */ }
Do you really need i at all? Since C++11 you can write range-based for loops and, in general, you may want(1) to use one of the algorithms provided by the Standard Library instead of a raw loop.
1) See e.g. this talk by Sean Parent.
You can do this:
for (std::size_t i = 0, vect_size = vect.size(); i < vect_size; ++i)
{
}
This way, you can limit the scope of vect_size.
Related
I am trying to do a product operand on the values inside of a vector. It is a huge mess of code.. I have posted it previously but no one was able to help. I just wanna confirm which is the correct way to do a single part of it. I currently have:
vector<double> taylorNumerator;
for(a = 0; a <= (constant); a++) {
double Number = equation involving a to get numerous values;
taylorNumerator.push_back(Number);
for(b = 0; b <= (constant); b++) {
double NewNumber *= taylorNumerator[b];
}
This is what I have as a snapshot, it is very short from what I actually have. Someone told me it is better to do vector.at(index) instead. Which is the correct or best way to accomplish this? If you so desire I can paste all of the code, it works but the values I get are wrong.
When possible, you should probably avoid using indexes at all. Your options are:
A range-based for loop:
for (auto numerator : taylorNumerators) { ... }
An iterator-based loop:
for (auto it = taylorNumerators.begin(); it != taylorNuemrators.end(); ++it) { ... }
A standard algorithm, perhaps with a lambda:
#include <algorithm>
std::for_each(taylorNumerators, [&](double numerator) { ... });
In particular, note that some algorithms let you specify a number of iterations, like std::generate_n, so you can create exactly n items without counting to n yourself.
If you need the index in the calculation, then it can be appropriate to use a traditional for loop. You have to watch for a couple pitfalls: std::vector<T>::size() returns a std::vector<T>::size_type which is typically identical to std::size_type, which is (1) unsigned and (2) quite possibly larger than an int.
for (std::size_t i = 0; i != taylorNumerators.size(); ++i) { ... }
Your calculations probably deal with doubles or some numerical type other than std::size_t, so you have to consider the best way to convert it. Many programmers would rely on implicit conversions, but that can be dangerous unless you know the conversion rules very well. I'd generally start by doing a static cast of the index to the type I actually need. For example:
for (std::size_t i = 0; i != taylorNumerators.size(); ++i) {
const auto x = static_cast<double>(i);
/* calculation involving x */
}
In C++, it's probably far more common to make sure the index is in range and then use operator[] rather than to use at(). Many projects disable exceptions, so the safety guarantee of at() wouldn't really be available. And, if you can check the range once yourself, then it'll be faster to use operator[] than to rely on the range-check built into at() on each index operation.
What you have is fine. Modern compilers can optimize the heck out of the above such that the code is just as fast as the equivalent C code of accessing items direclty.
The only optimization for using vector I recommend is to invoke taylorNumerator.reserve(constant) to allocate the needed storage upfront instead of the vector resizing itself as new items are added.
About the only worthy optimization after that is to not use vector at all and just use a static array - especially if constant is small enough that it doesn't blow up the stack (or binary size if global).
double taylorNumerator[constant];
If I was going through a loop, say iterating a vector, and I don't want to do an action on some item in the vector, I can do it in two ways:
This is the one I prefer to use:
vector<int> vec;
void loopFunction(int toIgnore) {
for (size_t index = 0; index < vec.size(); index++) {
if (vec[index] == toIgnore) continue;
// do stuff
}
}
This is the one I see most people use:
vector<int> vec;
void loopFunction(int toIgnore) {
for (size_t index = 0; index < vec.size(); index++) {
if (vec[index] != toIgnore) {
// do stuff
}
}
}
I know in the final results there is absolutely no difference. However, is there any difference under the hood since the second way opens a new scope to execute? Is any of these two preferred over the other?
Thanks
As stated in my comment, on a personal level, I prefer the first implementation using continue in order to prevent unnecessary code nesting and scope creation.
The only performance overhead from each, in addition to the normal code that will be implemented, is the evaluation of the expression in the if-statement. Since they both contain an expression to be evaluated, they're the same performance wise.
If you think about how this is compiled, for C/C++, its straight into assembly code. On that level no matter how you nest the code, it compiles into simple jmp and cmp commands. Therefore, regardless of the implementation, on compile, you'll have the ~same assembly code.
Either way you look at it, this is a micro-micro-micro optimization, if at all! Do what you prefer for code formatting and styling.
I think this is a very basic question but I couldn't just figure it out.
I was used to using arrays in C++ but I'm now starting to learn vectors.
I was making a test code, and I came across a question.
First of all, here's the code I made:
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
int main(){
vector<double> score(10);
for(vector<double>::size_type i=0;i<20;i++) {
cout<<"Enter marks for student #"<<i+1<<":"<<flush;
cin>>score[i];
}
double total = accumulate(score.begin(), score.end(),0);
cout<<"Total score:"<<total<<endl<<"Average score:"<<total/score.size()<<flush;
return 0;
}
In the for sentence in line #9, I am declaring i as a vector<double>::size_type type (because I was told to do so).
I tested the code with the type said above replaced with an int, and it worked perfectly fine.
Why is vector<double>::size_type preferred compared to int?
size_type is guaranteed to be large enough for the largest supported vector size, vector::max_size(). int is not: on many common platforms, int has 32 bits, while max_size() is considerably larger than 231.
If you know the size is (and will always be) a small number like 20, then you can get away with using int or any other integer type instead of size_type. If you were to change the program, for example to read the size from the input, then it would go horribly wrong if that value were larger than INT_MAX; while using size_type, it would continue working for any value up to max_size(), which you can easily test for.
The embedded type vector<double>::size_type relates to the return value for various vector methods, such as .size(), hence the preference in that case to use matching types (the int = 0 would generally result in a sign mismatch warning). E.g.
for (vector<double>::size_type i = 0; i < score.size(); ++i) { // types match
// ...
}
for (int i = 0; i < score.size(); ++i) { // types mismatch
// ...
}
std::vector::size_type is required to be large enough to represent the maximum number of elements that could be contained in a container, in this case vector<double>::max_size(). In general, it maps to size_t.
In your case, there is no explicit reason to use the vector<double>::size_type (although it would technically be better to use size_type) since the loop runs from 0 to 20 and both are int. Hence the following would be ok.
for (int i = 0; i < 20; ++i) { // loops 20 times
// ...
}
Additional notes:
Favour iterator based loops over index based ones:
for (vector<double>::iterator i = score.begin(); i != score.end(); ++i) {
// ...
}
It wasn't tagged as C++11, but if that is possible, the range based for loops deals with a lot of this.
for (double& i : score) {
// ...
}
Or even using a for_each with a lambda.
The vector size_type is what's used by vector to do size comparisons. If you had a loop that used an int as a counter and compared against the vector's actual size, you'd get warnings from the compiler about signed vs. unsigned integer comparisons:
for( int i=0; i<score.size(); i++ ){ // <-- signed vs. unsigned comparisons
// do something...
}
Your problem is two fold.
First, you are writing beyond the end of the std::vector -- the std::vector has 10 elements, and you are writing to 20.
In order to fix this, and to follow the Don't Repeat Yourself principle, you'd change your code as follows:
int main(){
std::vector<double> score(20);
for(std::vector<double>::size_type i=0;i<score.size();i++) {
where I both made the vector larger and used its size to determine how much to write.
Now, when we try to replace that long clause with int:
int main(){
std::vector<double> score(20);
for(int i=0;i<score.size();i++) {
we get a singed/unsigned comparison (probably):
i<score.size()
where score.size() is an unsigned value of type std::vector<double>::size_type, and i is an int.
Compilers often give warnings in these cases, as it is really easy to get nonsensical results (if i < 0, the comparison will usually result in the negative number comparing larger than the positive one!) In addition, if the size of the vector is larger than the max value of int (on some systems, as small as 32767, usually at least 2147483647, and sometimes much larger -- this is a value the compiler is reasonably free to pick for itself, the C++ standard does not specify it fully), the loop will fail spectacularly.
Now, while the type of std::vector<double>::size() is std::vector<double>::size_type, this is (in every implementation I've experienced) just std::size_t. So that is a shorter way to say it:
for(std::size_t i=0;i<score.size();i++) {
(std::size_t is defined in <cstddef> as an aside).
If you are programming in C++11, you can do one better:
int i=0;
for(double& student:score) {
std::cout<<"Enter marks for student #"<<++i<<":"<<std::flush;
std::cin>>student;
}
which is a range-based for loop and avoid the problem of indexing entirely.
Recently, I've been thinking about all the ways that one could iterate through an array and wondered which of these is the most (and least) efficient. I've written a hypothetical problem and five possible solutions.
Problem
Given an int array arr with len number of elements, what would be the most efficient way of assigning an arbitrary number 42 to every element?
Solution 0: The Obvious
for (unsigned i = 0; i < len; ++i)
arr[i] = 42;
Solution 1: The Obvious in Reverse
for (unsigned i = len - 1; i >= 0; --i)
arr[i] = 42;
Solution 2: Address and Iterator
for (unsigned i = 0; i < len; ++i)
{ *arr = 42;
++arr;
}
Solution 3: Address and Iterator in Reverse
for (unsigned i = len; i; --i)
{ *arr = 42;
++arr;
}
Solution 4: Address Madness
int* end = arr + len;
for (; arr < end; ++arr)
*arr = 42;
Conjecture
The obvious solutions are almost always used, but I wonder whether the subscript operator could result in a multiplication instruction, as if it had been written like *(arr + i * sizeof(int)) = 42.
The reverse solutions try to take advantage of how comparing i to 0 instead of len might mitigate a subtraction operation. Because of this, I prefer Solution 3 over Solution 2. Also, I've read that arrays are optimized to be accessed forwards because of how they're stored in the cache, which could present an issue with Solution 1.
I don't see why Solution 4 would be any less efficient than Solution 2. Solution 2 increments the address and the iterator, while Solution 4 only increments the address.
In the end, I'm not sure which of these solutions I prefer. I'm think the answer also varies with the target architecture and optimization settings of your compiler.
Which of these do you prefer, if any?
Just use std::fill.
std::fill(arr, arr + len, 42);
Out of your proposed solutions, on a good compiler, neither should be faster than the others.
The ISO standard doesn't mandate the efficiency of the different ways of doing things in code (other than certain big-O type stuff for some collection algorithms), it simply mandates how it functions.
Unless your arrays are billions of elements in size, or you're wanting to set them millions of times per minute, it generally won't make the slightest difference which method you use.
If you really want to know (and I still maintain it's almost certainly unnecessary), you should benchmark the various methods in the target environment. Measure, don't guess!
As to which I prefer, my first inclination is to optimise for readability. Only if there's a specific performance problem do I then consider other possibilities. That would be simply something like:
for (size_t idx = 0; idx < len; idx++)
arr[idx] = 42;
I don't think that performance is an issue here - those are, if at all (I could imagine the compiler producing the identical assembly for most of them), micro optimizations hardly ever necessary.
Go with the solution that is most readable; the standard library provides you with std::fill, or for more complex assignments
for(unsigned k = 0; k < len; ++k)
{
// whatever
}
so it is obvious to other people looking at your code what you are doing. With C++11 you could also
for(auto & elem : arr)
{
// whatever
}
just don't try to obfuscate your code without any necessity.
For nearly all meaningful cases, the compiler will optimize all of the suggested ones to the same thing, and it's very unlikely to make any difference.
There used to be a trick where you could avoid the automatic prefetching of data if you ran the loop backwards, which under some bizarre set of circumstances actually made it more efficient. I can't recall the exact circumstances, but I expect modern processors will identify backwards loops as well as forwards loops for automatic prefetching anyway.
If it's REALLY important for your application to do this over a large number of elements, then looking at blocked access and using non-temporal storage will be the most efficient. But before you do that, make sure you have identified the filling of the array as an important performance point, and then make measurements for the current code and the improved code.
I may come back with some actual benchmarks to prove that "it makes little difference" in a bit, but I've got an errand to run before it gets too late in the day...
Which of the following is better and why? (Particular to c++)
a.
int i(0), iMax(vec.length());//vec is a container, say std::vector
for(;i < iMax; ++i)
{
//loop body
}
b.
for( int i(0);i < vec.length(); ++i)
{
//loop body
}
I have seen advice for (a) because of the call to length function. This is bothering me. Doesn't any modern compiler do the optimization of (b) to be similar to (a)?
Example (b) has a different meaning to example (a), and the compiler must interpret it as you write it.
If, (for some made-up reason that I can't think of), I wrote code to do this:
for( int i(0);i < vec.length(); ++i)
{
if(i%4 == 0)
vec.push_back(Widget());
}
I really would not have wanted the compiler to optimise out each call to vec.length(), because I would get different results.
I like:
for (int i = 0, e = vec.length(); i != e; ++i)
Of course, this would also work for iterators:
for (vector<int>::const_iterator i = v.begin(), e = v.end(); i != e; ++i)
I like this because it's both efficient (calling end() just once), and also relatively succinct (only having to type vector<int>::const_iterator once).
I'm surprised nobody has said the obvious:
In 99.99% of cases, it doesn't matter.
Unless you are using some container where calculating size() is an expensive operation, it is unfathomable that your program will go even a few nanoseconds slower. I would say stick with the more readable until you profile your code and find that size() is a bottleneck.
There are two issues to debate here:
The variable scope
The end condition re-evaluation
Variable scope
Normally, you wouldn't need the loop variable to be visible outside of the loop. That's why you can declare it inside the for construct.
End condition re-evaluation
Andrew Shepherd stated it nicely: it means something different to put a function call inside the end condition:
for( vector<...>::size_type i = 0; i < v.size(); ++i ) { // vector size may grow.
if( ... ) v.push_back( i ); // contrived, but possible
}
// note: this code may be replaced by a std::for_each construct, the previous can't.
for( vector<...>::size_type i = 0, elements = v.size(); i != elements; ++i ) {
}
Why is it bodering you?
Those two alternatives dont see to be doing the same. One is doing a fixed number of iterations, while the other is dependant on the loops body.
Another alternative colud be
for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
//loop body
}
Unless you need the loop variable outside the loop, the second approach is preferable.
Iterators will actually give you as good or better performance. (There was a big comparison thread on comp.lang.c++.moderated a few years back).
Also, I would use
int i = 0;
Rather than the constructor like syntax you're using. While valid, it's not idiomatic.
Somewhat unrelated:
Warning: Comparison between signed and unsigned integer.
The correct type for array and vector indices is size_t.
Strictly speaking, in C++ it is even std::vector<>::size_type.
Amazing how many C/C++ developers still get this one wrong.
Let's see on the generated code (I use MSVS 2008 with full optimization).
a.
int i(0), iMax(vec.size());//vec is a container, say std::vector
for(;i < iMax; ++i)
{
//loop body
}
The for loop produces 2 assembler instructions.
b.
for( int i(0);i < vec.size(); ++i)
{
//loop body
}
The for loop produces 8 assembler instructions. vec.size() is successfully inlined.
c.
for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end(); i != e; ++i)
{
//loop body
}
The for loop produces 15 assembler instructions (everything is inlined, but the code has a lot of jumps)
So, if your application is performance critical use a). Otherwise b) or c).
It should be noted that the iterator examples:
for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
//loop body
}
could invalidate the loop iterator 'it' should the loop body cause the vector to reallocate. Thus it is not equivalent to
for (int i=0;i<vec.size();++i){
//loop body
}
where loop body adds elements to vec.
Simple question: are you modifying vec in the loop?
answer to this question will lead to your answer too.
jrh
It's very hard for a compiler to hoist the vec.length() call in the safe knowledge that it's constant, unless it gets inlined (which hopefully it often will!). But at least i should definitely be declared in the second style "b", even if the length call needs to be "manually" hoisted out of the loop!
This one is preferable:
typedef vector<int> container; // not really required,
// you could just use vector<int> in for loop
for (container::const_iterator i = v.begin(); i != v.end(); ++i)
{
// do something with (*i)
}
I can tell right away that the vector
is not being updated
anyone can tell what is happening
here
I know how many loops
v.end() returns pointer one past the
last element so there's no overhead
of checking size
easy to update for different
containers or value types
(b) won't calculate/call the function each time.
-- begin excerpt ----
Loop Invariant Code Motion:
GCC includes loop invariant code motion as part of its loop optimizer as well as in its partial redundancy elimination pass. This optimization removes instructions from loops, which compute a value which does not change throughout the lifetime of a loop.
--- end excerpt --
More optimizations for gcc:
https://www.in.redhat.com/software/gnupro/technical/gnupro_gcc.php3
Why not sidestep the issue entirely with BOOST_FOREACH
#include <boost/foreach.hpp>
std::vector<double> vec;
//...
BOOST_FOREACH( double &d, vec)
{
std::cout << d;
}