use of "&" with auto [duplicate] - c++11

This question already has answers here:
Range based loop: get item by value or reference to const?
(5 answers)
Closed 6 years ago.
When we need to use " &" and when not to?
for example in below, both for loops produce identical result.
std::vector< Product* > itemByColor = pF.by_color( vecProds, Color::Red );
for( auto i : itemByColor )
{
std::cout << " product name <<" << i->name<< std::endl;
}
AND
for( auto& i : itemByColor )
{
std::cout << " product name <<" << i->name<< std::endl;
}

More or less the same as whether you would decide to type std::string or (const) std::string&. That is, whether you want to copy the object or to take a reference to it.
std::vector<int> my_vector{ 1, 2, 3, 4, 5 };
int copy = my_vector[ 0 ];
int& reference = my_vector[ 0 ];
++copy;
std::cerr << my_vector[ 0 ] << '\n'; // Outputs '1', since the copy was incremented, not the original object itself
++reference;
std::cerr << my_vector[ 0 ] << '\n'; // Outputs '2', since a reference to the original object was incremented
// For each 'n' in 'my_vector', taken as a copy
for( auto n : my_vector )
{
// The copy ('n') is modified, but the original remains unaffected
n = 123;
}
// For each 'n' in 'my_vector', taken as a reference
for( auto& n : my_vector )
{
// The original is incremented by 42, since 'n' is a reference to it
n += 42;
}
// At this point, 'my_vector' contains '{ 44, 44, 45, 46, 47 }'

Related

Custom sort and key uniqueness in std::map C++

Consider the follow std::map code.
The idea is to sort keys based only a double value even though the key contains more information.
In the custom sort used for the map, there are 3 test conditions the first of which does not work as expected.
I would like to understand why before I assume the next two actually behave as I expect them too.
Test choices 2 and 3 explicit that I do not care about the content of s_Rule (some pointer containing information) for sorting purposes but how does that also break the key mechanism of map.
In fact, 2 and 3 are literally the same since if double == double and ptr == ptr than the key is obviously the same.
This may (or may not) be related to question :
How can I declare a custom sort function on std::map declaration?
in which Simon9987 asks at the end why sort has broken the std::find function
class s_Rule
{
int x;
s_Rule() : x(0) {} // irrelevant content for question
}
typedef std::pair<double, s_Rule*> ruleSavedData;
struct sortByDouble
{
bool operator()(const ruleSavedData& a, const ruleSavedData& b) const
{
return a.first < b.first; // // not ok
// return a.first < b.first || (a.first == b.first && a.second != b.second); // ok
// return a.first <= b.first; // ok
}
};
typedef std::map<ruleSavedData, std::tuple<int, int, int>, sortByDouble> t_splitRulePool;
t_splitRulePool _splitRulePool;
auto test1 = new s_Rule();
auto test2 = new s_Rule();
auto test3 = new s_Rule();
const auto pp1 = ruleSavedData(687.00, test1);
_splitRulePool[pp1] = std::tuple<int,int,int>({1, 0, 0});
for (const auto& sr : _splitRulePool)
std::cout << sr.first.first << " with rule: " << sr.first.second << " and value " << std::get<0>(sr.second) << std::endl;
// Output: 687 with rule: 000001F9B60509E0 and value 1
const auto pp2 = ruleSavedData(688.00, test2);
_splitRulePool[pp2] = std::tuple<int, int, int>({ 2, 0, 0 });
for (const auto& sr : _splitRulePool)
std::cout << sr.first.first << " with rule: " << sr.first.second << " and value " << std::get<0>(sr.second) << std::endl;
// Output:
// 687 with rule: 000001F9B60509E0 and value 1
// 688 with rule: 000001F9B60506E0 and value 2
const auto pp3 = ruleSavedData(687.00, test3);
_splitRulePool[pp3] = std::tuple<int, int, int>({ 3, 0, 0 });
for (const auto& sr : _splitRulePool)
std::cout << sr.first.first << " with rule: " << sr.first.second << " and value " << std::get<0>(sr.second) << std::endl;
// Output:
// 687 with rule: 000001F9B60509E0 and value 3 -> key of pp1 gets overwritten with sortByDouble choice 1 but not with the others
// 688 with rule: 000001F9B60506E0 and value 2
// "Expected" output:
// 687 with rule: 000001F9B60509E0 and value 1
// 687 with rule: (&pp3) and value 3 // comes after simply because first sort < key is not true
// 688 with rule: 000001F9B60506E0 and value 2
delete test1;
delete test2;
delete test3;

Why I cannot use a decltype in range-for with multi-dimension arrays?

I have a problem here. I am trying to use decltype in range-for loop for using multi-dimension array:
int a[][4]{
{0, 1, 2, 3 },
{4, 5, 6, 7 },
{8, 9, 10, 11}
};
for (auto& row : a) { // reference is needed here to prevent array decay to pointer
cout << "{";
for (auto col : row)
cout << col << ", ";
cout << "}" << endl;
}
decltype (*a) row{ *a};
cout << sizeof(row) << endl;
cout << typeid(row).name() << endl;
// for (decltype(*a) row : *a) {
// for (int col : row)
// cout << col << ", ";
// cout << endl;
// }
With auto I can easily iterate over the the array But with decltype it doesn't work for me.
What I get above if I uncomment the code is: cannot convert from int to int(&)[4].
That is because the line for(decltype(*a) row : *a) is incorrect. Try to read it correctly: for each array of 4 int from a, not from *a.
The code may look like:
for (decltype(*a) row : a) {
for (int col : row)
cout << col << ", ";
cout << endl;
}
Dereferencing a (*a) with decltype will yield an array of 4 integers. So the type is int[4]. Unlike using keyword auto where it yields int*.

Iterating over a vector with std::adjacent_find and custom predicate

I am having trouble searching for and printing out pairs of elements in a vector that are separated by 2 from left to right. I need to collect the pairs
The example data that I am operating on is:
std::vector<int> myvector = { 1, 3, 3, 5, 7, 9, 13, 10, 12 };
Given that the std::adjacent_find predicate is:
static const auto gAdjacentPred = [](
const int& lhs, const int& rhs) {
std::cout
<< "(" << lhs << ":" << rhs << ")?"
<< std::string((rhs == lhs+2)? "true" : "false")
<< std::endl;
return (rhs == lhs+2);
};
I was expecting to get the following result (with multiple calls to the predicate along the way):
{1,3}, {3,5}, {5,7}, {7,9} & {10,12}
Ideally thought (and I have no idea how to do this) I would like to merge the values that satisfy the predicate in the middle of the input data ... 3, 5, 7, 9 ... as a single result {3, 9}.
The problem is that I do not really understand how to properly loop over the collection. I did see that std::next(iter) is a trick that I can use to peek ahead at the right most value satisfying the lambda, however this can sometimes point to the end of the collection.
I was expecting that the way I was looping over the data would show multiple calls to the predicate as it iterated over the collection - as it turns out it only calls the predicate function one time (when I assign to the adjIter. Also, in the results I see that the pair 13 & 10 seems to satisfy the predicate. Could someone explain what is going on here as I need to find pairs from left to right that differ by some value - in my case here 2 (with the left side less than the right (I am searching for increasing values from left to right).
(1:3)?true
{1,3}
{3,5}
{7,9}
{13,10}
The problem is that the last pair is also considered
static const auto gAdjacentPred = [](
const int& lhs, const int& rhs) {
std::cout
<< "(" << lhs << ":" << rhs << ")?"
<< std::string((rhs == lhs+2)? "true" : "false")
<< std::endl;
return (rhs == lhs+2);
};
std::vector<int> myvector = { 1, 3, 3, 5, 7, 9, 13, 10, 12 };
auto adjIter = std::adjacent_find (
myvector.begin(), myvector.end(),
gAdjacentPred);
while (adjIter != myvector.cend()) {
auto second = std::next(adjIter);
// print both sides
if (second != myvector.cend()) {
std::cout << "{" << *adjIter << "," << *second << "}" << std::endl;
adjIter +=2;
} else {
adjIter++;
}
}

Why does a vector value stored in an integer give different results?

I have very recently started using vectors in C++.The purpose of the program I am trying to write is to determine the first missing positive number. Given an input array A : [ -9, 12, -1, 0, 1 ] the expected output is 2. I coded it -
int Solution::firstMissingPositive(vector<int> &A)
{
std::sort(A.begin(),A.end()); //sorting vector
bool Negative=false;
int flag;
int i=0;
for(i=0;i<A.size();++i)
{
if(A[i]<=0)
{
Negative=true;
std::cout<<"\nwe found a -ve number or 0";
}
else if( (A[i]>0) && (A[i+1]!=A[i]+1) )
{
Negative=false;
std::cout<<"\ncomparing # ="<<i<<" which = "<<A[i];
std::cout<<"\ncomparing # ="<<i+1<<" which = "<<A[i+1];
flag=A[i]+1; //The faulty statement
std::cout<<"\n\n missing number(A[i]+1) # ="<<A[i]+1;
std::cout<<"\n\n missing number(flag) # ="<<flag;
break;
}
}
//do something more
}
With this output -
-9 -1 0 1 12
we found a -ve number or 0
we found a -ve number or 0
we found a -ve number or 0
comparing # =3 which = 1
comparing # =4 which = 12
missing number(A[i]+1) # =2
missing number(flag) # =20
I found this interesting because, to me, it looks like I cannot use an integer to store the value of a vector.
Trying to debug it I found changing the flag assignment to flag = A[i]+2 makes the resultant print 30.
I've read other questions on SO where it suggests using vector.at(i) instead of the [] operator as a better practice. Changing this does not reflect any change for my code.
Changing flag to vector<int> gives me a dirty error which I'm not sure about.
Isn't A[i]+1 syntactically equivalent to an integer value? And if it is, why can I not store it?
Reducing your code to an MCVE quickly demonstrates that the problem is with your output formatting, putting the "\n" at the beginning of the statement is an uncommon practice for precisely this reason. You're not seeing 20, what you're seeing is the "2" from flag followed by a zero printed elsewhere.
#include <algorithm>
#include <iostream>
#include <vector>
void solve(std::vector<int>& A)
{
std::sort(A.begin(),A.end()); //sorting vector
bool Negative=false;
int flag;
int i=0;
for(i=0;i<A.size();++i)
{
if(A[i]<=0)
{
Negative=true;
std::cout<<"we found a -ve number or 0\n";
}
else if( (A[i]>0) && (A[i+1]!=A[i]+1) )
{
Negative=false;
std::cout<<"comparing # ="<<i<<" which = "<<A[i]<<'\n';
std::cout<<"comparing # ="<<i+1<<" which = "<<A[i+1]<<'\n';
flag=A[i]+1; //The faulty statement
std::cout<<"missing number(A[i]+1) # ="<<A[i]+1<<'\n';
std::cout<<"missing number(flag) # ="<<flag<<'\n';
break;
}
}
//do something more
}
int main() {
std::vector<int> A { -9, 12, -1, 0, 1 };
solve(A);
std::cout << "and we're done\n";
}
Output (see http://ideone.com/zb9fNX)
we found a -ve number or 0
we found a -ve number or 0
we found a -ve number or 0
comparing # =3 which = 1
comparing # =4 which = 12
missing number(A[i]+1) # =2
missing number(flag) # =2
and we're done
I should also point out that your test for "A[i+1]" will lead to an out of bounds array access if it ever tries to read the last element in the array. You should change
for(i=0;i<A.size();++i)
to
for(i=0;i<A.size() - 1;++i)
or more conventially,
for(i=1;i<A.size();++i)
and use "A[i-1]" instead of "A[i+1]" to fetch the previous value.
For example:
#include <algorithm>
#include <iostream>
#include <vector>
void solve(std::vector<int>& A)
{
std::sort(A.begin(),A.end()); //sorting vector
int expected = 0;
int missing = 0;
for(int i = 1; i < A.size(); ++i)
{
if (A[i] <= 0) {
std::cout << "we found " << A[i] << "\n";
continue;
}
if (A[i-1] <= 0) {
expected = 1;
} else {
expected = A[i-1] + 1;
}
if (A[i] == expected)
continue;
std::cout << "A[" << i-1 << "] = " << A[i-1] << '\n';
std::cout << "expecting " << expected << '\n';
std::cout << "A[" << i << "] = " << A[i] << '\n';
missing = expected;
std::cout << "missing number: " << expected << '\n';
break;
}
//do something more
}
int main() {
std::vector<int> A { -9, 12, -1, 0, 1 };
solve(A);
std::cout << "and we're done\n";
}
http://ideone.com/AIw4oU

Why is problemsPathCoordinate vector of a vector of a pair empty?

I have tried to fill a smaller vector of a vector of pairs with some contents from a bigger vector of a vector of pairs without success. Below is the relevant code with couts and their output. Hopefully this is detailed enough.
/*******************Problems Occur*****************/
int iFirst=problemsStartAt;//first index to copy
int iLast=problemsEndAt-1;//last index -1, 11th stays
int iLen=iLast-iFirst;//10-8=2
//if(problemsStartAt!=0)//I.a
if(problemsStartAt!=0&&problemsEndAt!=0)//I.b
{
v_problem_temp=allPathCoordinates[problemsStartAt];
cout<<"266:"<<v_problem_temp.size()<<endl;
cout<<"267:"<<allPathCoordinates.at(1).size()<<endl;
for(vector<pair<int,int>>::iterator it2=v_problem_temp.begin();
it2!=v_problem_temp.end();
++it2)
{
apair=*it2;
point[apair.first][apair.second]=Yellow;
cout<<apair.first<<","<<apair.second<<endl;
}
problemsPathCoordinate.resize(iLen);
cout<<"iLen*sizeof(problemsPathCoordinate):" <<iLen*sizeof(problemsPathCoordinate)<<endl;
memcpy(&problemsPathCoordinate[0],&allPathCoordinates[iFirst],iLen*sizeof(problemsPathCoordinate));
cout<<"279:problemsPathCoordinate.size():"<<problemsPathCoordinate.size()<<endl;
problemsPathCoordinate.resize(iLen);
memcpy(&problemsPathCoordinate[0],&allPathCoordinates[iFirst],iLen*sizeof(problemsPathCoordinate));
cout<<"283:problemsPathCoordinate.size():"<<problemsPathCoordinate[0].size()<<endl;
cout<<"284:problemsPathCoordinate.size():"<<problemsPathCoordinate[1].size()<<endl;
cout<<"286:allPathCoordinates.size():"<<allPathCoordinates.size()<<endl;
cout<<"287:allPathCoordinates.size():"<<allPathCoordinates.size()<<endl;
//from http://stackoverflow.com/questions/35265577/c-reverse-a-smaller-range-in-a-vector
}
Output:
759: path NOT full-filled, number: 8
755: Problems START here at:8
759: path NOT full-filled, number: 9
700: Problems END here at: 11
266:0
267:0
iLen*sizeof(problemsPathCoordinate):72
279:problemsPathCoordinate.size():3
283:problemsPathCoordinate.size():0
284:problemsPathCoordinate.size():0
286:allPathCoordinates.size():79512
287:allPathCoordinates.size():79512
time:39 seconds
Why are the three problemsPathCoordinate elements empty. How to fix it?
Bo
for (vector< vector > >::iterator it = allPathCoordinates.begin(); it != allPathCoordinates.end(); ++it)
{
allPathCoordinates.erase(allPathCoordinates.begin()+5,allPathCoordinates.end()-2);
v_temp = *it;
//cout<<"v_temp.size():"<
for (vector<pair<int,int> >::iterator it2 = v_temp.begin(); it2 != v_temp.end(); ++it2) {
//v_temp.erase(v_temp.begin()+2);
apair = *it2;
//cout << "(" << apair.first << "," << apair.second << ") ; ";
openPoints[apair.first][apair.second]=0;
closedPoints[apair.first][apair.second]=1;
allObstacles[apair.first][apair.second]=Wall;
point[apair.first][apair.second]=Yellow;
}
/

Resources