Setting vector elements in range-based for loop
Change this loop statement
for(auto n: *CTdata)
to
for(auto &n : *CTdata)
that is you have to use references to elements of the vector.
Erasing vector elements while in a range-based loop vs. standard loop
In the first case, for each iteration std::vector::size
function is being called. Thus, if you delete all the elements in the first iteration, std::vector::size
function which is called before the start of second iteration will return 0. Therefore, second iteration won't happen because the condition i < test.size()
is not satisfied.
In the second case, range-based for loop uses iterators instead of std::vector::size
function. When you call std::vector::erase
you invalidate all the iterators including the end()
iterator. Therefore, second case is actually UB (Undefined Behavior) and you should never rely on that.
From the docs:
std::vector::erase
... Invalidates iterators and references at or after the point of the
erase, including the end() iterator.
About using range based for loop over a vector of vectors
each element of e is a vector, each element of e[node] is int.
Why doesn't range-based for loop modifiy container elements?
Your for loop copies v, then sorts it. The original is untouched. What you want is for (auto &v : arr)
.
Can range based for loop work for assignment?
Is it possible to use/implement a ranged base loop to assign numbers to an array?
Yes, use a reference:
for (auto & i : X){
// ^
i = 1;
}
vectors in range based for loop
for(auto i : anotherVector)
cout << anotherVector[i] << endl;
This code doesn't do what you think it does. The range-based for loop iterates over values, not over indices. In other words, the loop variable (i
) is assigned all ements of the vector in turn.
To replicate the functionality of your first loop, you need this:
for (auto i : anotherVector)
cout << i << endl;
What your original code was doing was take an element of the vector, and use it to index into the vector again. That's why the numbers were off by one (since the vector held number n + 1
at position n
). Then, the final output (81 in your case) was effectively random and the result of Undefined Behaviour—you were reaching past the end of the vector.
C++ range-based for loop and copy of element
As mentioned in the comment by @Fureeish one problem with the second version is inserting to the subsets vector while iterating over the subsets vector.
for (vector<int> subset : subsets)
{
subset.push_back(current_num);
subsets.push_back(subset); // Should not modify vector while iterating on it
}
The range statement expands to something like:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
The __end expression is expanded before the iterations. For a vector this could be calculating the address at vector.data[size]. If the loop pushes new elements into the vector, the __end expression is no longer correct.
If you iterated over a copy of the vector instead, the range statement would work. For example:
for (vector<int> subset : vector<vector<int>>(subsets))
{
subset.push_back(current_num);
subsets.push_back(subset);
}
Fill a vector of pointers with a range-based for loop
Take the elements by reference:
for (auto& r : v)
pv.push_back(&r);
Your original range-based for loop iterates the vector by value, making each i
a fresh copy of each item. The expression &i
therefore does not retrieve the address of element inside v
.
Iterating by reference, each r
refers to the very element inside v
, and thus the address-of expression &r
correctly retrieve the element's address.
Range based for loop: Iterate over vector extended with one element
It can be done using the upcoming ranges feature.
Here's an example using Eric Niebler's range-v3
library:
#include <iostream>
#include <vector>
#include <range/v3/view/concat.hpp>
#include <range/v3/view/single.hpp>
int main() {
std::vector<int> a = {1, 5, 3};
int additional = 6;
for (auto i : ranges::concat_view(ranges::single_view{additional}, a)) {
std::cout << i;
}
}
See it live!
by using views, all iterator operations are lazy, and no extra memory is used (e.g.: no extra vectors/arrays are created)
Or, without the for
loop:
ranges::copy(ranges::concat_view(ranges::single_view{additional}, a), ranges::make_ostream_joiner(std::cout, ","));
See it live!
(Honestly, I like the for
version better, though)
Standard-compliant solution
There's a small issue with the solution above: concat_view
did not make it into C++20. If you want a strictly compliant solution, you may want to create your own version, or use join_view
instead:
#include <iostream>
#include <vector>
#include <ranges>
int main() {
std::vector<int> a = {1, 5, 3};
int additional = 6;
std::vector v{{additional}, a};
for(int i : std::ranges::join_view{v}) {
std::cout << i;
}
}
Related Topics
Can Class Template Constructors Have a Redundant Template Parameter List in C++20
Iterate Through a C++ Vector Using a 'For' Loop
Why How to Use 'Std::Move' on a 'Const' Object
Best Method for Storing This Pointer for Use in Wndproc
Can a Cast Operator Be Explicit
What Is the Underlying Type of a C++ Enum
How to Access Private Data Members Outside the Class Without Making "Friend"S
Why Is There No Reallocation Functionality in C++ Allocators
How Bad Is Redefining/Shadowing a Local Variable
How to Set the Padding of Qtableview Cells Through CSS
#Include Errors Detected in VScode
Is There Actually a Reason Why Overloaded && and || Don't Short Circuit
Does "Std::Size_T" Make Sense in C++
How Will I Know Whether Inline Function Is Actually Replaced at the Place Where It Is Called or Not