### Hikikomorichka's blog

By Hikikomorichka, history, 6 weeks ago,

I recently came across some very cool C++ tricks from some of the best coders which can help increase your code efficiency as well as make the code very neat , clean and easy to understand.I would be sharing some of these here.

1.Normally to find minimum among few elements we use something like this.

int a = min(x1,min(x2,min(x3,min(x4,x5))));


Instead of this we can use this.

int a = min({x2,x2,x3,x4,x5});


2.Using emplace_back in place of push_back

In C++ 11,emplace_back works just like push_back adding elements at the end of a vector. emplace_back is faster than push_back as push_back first creates a temporary variable and then adds it to the end of vector.

vector<int> v;
v.push_back(1); // Slower
v.emplace_back(2); //Faster


3.Using tuples

//Normally we use something like this
pair<int,pair<int,pair<char,int > > > p;
p=make_pair(1,make_pair(2,make_pair('a',3)));
// To access different elements we use something like this.
// TO access 1
int x=p.first;
// To access 2
int y=p.second.first;
//To access 'a'
char z=p.second.second.first;
//TO access 3
int s=p.second.second.second

// Instead of the above usage we can use tuples

tuple(int,int,char,int) t1=make_tuple(1,2,'a',3);
// TO access the ith element of a tuple we can use get<i> nameOfTuple
cout << get<0> t1 <<"  "<<get<2>t1<<endl; // Prints 1 and 'a'


4.Lambda Functions

Yes we have Lambda functions in C++ as well.Lambda functions are functions which do not have a name.Normally when we have to write a comparator function for usage whenever we want to sort an array according to a certain rule.Sometimes these functions are very simple and we do not need to explicitly write a comparator function for that.This can be simply done using lambda function.

bool cmp(int a,int b){
return a>b;
}

vector<int> v;
v.emplace_back(1);
v.emplace_back(101);
v.emplace_back(5);
v.emplace_back(12);
v.emplace_back(-4);

// Now sorting

sort(v.begin(),v.end(),cmp);

// The above statement can be simple written without the comparator function
// using the lambda function

sort(v.begin(),v.end(),[](int a,int b){return a>b;});

// A lambda function is written like   [](argument1,argument2,.....){//code}


5.Using Conditional Operators

Using conditional operators can make the code clean and efficient.

// Without conditional operators
if (a & 1) { // when a is odd
a=a*2;
}
else{
a=a+1;
}

// With conditional operators

a&1?a*=2:a+=1;


6. Bit Manipulation

// Conventional way to check ith bit set or not.
bool isSet(int num,int i){ // bit is counted from lsb to msb ..int this order 0th bit,1st bit...and so on
for(int j=0;j<i;j++){
num=num/2;
}
if(num&1)return true;
return false;
}

// Using shift operator
int t= num & (1<<i); // t is non zero (2^(i)) to be exact if ith bit is set else 0
// Setting ith bit
num|=(1<<i);
// flipping ith bit
num ^ = (1<<i); // ^ is the xor operator
// clearing the ith bit
num=num & ~(1<<i);


7.Using auto

Auto automatically determines the data type of the variable at run time and hence you need not to specify the data type of the variable.It also makes iterating over containers easy(code wise efficient).

 auto a = 1; // a will become 'int'
auto b = 1LL; // b will become 'long long'
auto c = 1.0; // c will become 'double'
auto d = "variable"; // d will become 'string'

vector<int > v;
v.push_back(5);
v.push_back(10);
v.push_back(13);
// or instead you can write vector<int>v={5,10,13};
//  Now to print the contents of v  you can use
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
cout << *it << ' ';
// or you can use auto keyword to ease your work
for(auto n:v)
cout<<n<<" ";
// Same goes for set , map and other data structures.
set<pair<int,int> >s;
s.insert({1,2}) // or you can use s.insert(make_pair(1,2))
s.insert({5,6}) //  or s.insert(make_pair(5,6))
// or simply you can write set<pair<int,int> >s={ {1,2} , {5,6} }
// for printing the elements present in s
for (set<pair<int,int>>::iterator it = s.begin(); it != s.end(); ++it)
cout << (*it).first << '  '<<(*it).second<<"\n";
// or you can use auto to print its elements
for(auto x:s)
cout<<x.first<<" "<<x.second<<"\n";


• +13

 » 6 weeks ago, # | ← Rev. 3 →   +77 \2. This is a completely wrong example of emplace_back usage, no one would use C++ if compilers couldn't optimize push_back(int) or even push_back(pair). emplace_back is used for two reasons: a) it's sometimes shorter, b) it's faster when the elements are containers themselves. vector> arr; arr.push_back(make_pair(1, 2)); // good arr.emplace_back(make_pair(1, 2)); // same speed arr.emplace_back(1, 2); // same speed but much shorter emplace_back forwards its arguments right to the constructor so you can use 1, 2 and it'll be the same as pair(1, 2) (almost, because the latter also calls move constructor but oh well).Here's when emplace_back is slightly faster: vector> arr; arr.push_back(vector{1, 2, 3}); // constructs vector and then moves it to the outer container arr.emplace_back(vector{1, 2, 3}); // same arr.emplace_back(initializer_list{1, 2, 3}); // faster, perfect-forwards the data right to the constructor 
 » 6 weeks ago, # |   +53 \3. You mistyped the tuple syntax. It should be: tuple t1 = make_tuple(1, 2, 'a', 3); // To access the ith element of a tuple we can use get(nameOfTuple) cout << get<0>(t1) <<" " << get<2>(t1) << endl; // Prints 1 and 'a' There are three points of interest:a) It's tuple, not tuple(int, int, char, int) because these are template parameters, not function parameters.b) get(x) is no magic, it's just a template function get called with a single argument x. There is no special syntax here.c) No one uses make_tuple these days, you should try initializer lists: tuple t1{1, 2, 'a', 3}; You could argue it's better to use auto and make_tuple like this, but personally I prefer making sure variable types are expected.
 » 6 weeks ago, # |   +45 In this statement:auto d = "variable"; // d will become 'string'd will actually become const char*
 » 6 weeks ago, # |   +25 \4. The point of lambdas has never been having 'functions which do not have a name'. C++ lambdas simplify variable capture. Here's what it means:Pretend that you want to sort an array, but instead of comparing values themselves, you compare priority_of[value]. In Python it's really simple: priority_of = ... a.sort(key=lambda value: priority_of[value]) What about C++? void solve() { ... auto priority_of = ... sort(a.begin(), a.end(), uh?..); ... } Hm, so what do you pass as a comparator? Maybe an external function? void compare(int i, int j) { return priority_of[i] < priority_of[j]; } void solve() { ... auto priority_of = ... sort(a.begin(), a.end(), compare); ... } Oops, priority_of is a local variable so compare can't access it. Of course, you could make it global but that might become a problem if you use recursion, and copying is slow. You could also try pointers... but lambdas provide a simple solution: void solve() { ... auto priority_of = ... sort(a.begin(), a.end(), [&priority_of](int i, int j) { return priority_of[i] < priority_of[j]; }); ... } See this magic, [&priority_of]? This is called capture list. & before variable name means that the list is passed by reference and is not copied. You can shorten the capture list like [&], but this means all variable references are stored so it may be a bit slower.
•  » » 6 weeks ago, # ^ |   0 Actually, using [&] will only capture the references to the variables you call inside the lambda, so it will be the same speed.
•  » » » 6 weeks ago, # ^ |   0 Unfortunately I don't have any code at the moment but I remember that replacing [&] with [&var] helped me once.Here's another idea. When you capture an integer by reference, this means a pointer to it is stored. When you access this variable later, it takes a bit more time than reading the integer directly. So it's better to capture primitives by value and other variables by reference, like this: int x; vector a; auto lambda = [x, &a](...) { ... }; 
 » 6 weeks ago, # |   +18 You don't need to use auto for range-based for loops. You can just use like this: vector v = {5, 10, 13}; for (int i : v) cout << i << " "; The situation where auto is useful here is if you want to iterate using iterators: vector v = {5, 10, 13}; for (auto it = v.begin(); it != v.end(), it++) cout << *it << " "; Also, since C++17, you can do this: set> s; s.insert({1,2}); s.insert({5,6}); for (auto [a, b] : s) cout << a << " " << b << endl; 
•  » » 6 weeks ago, # ^ | ← Rev. 2 →   0 A bit offtopic but I think I should mention that this: s.insert({1, 2}); s.insert({5, 6}); is identical to this: s.emplace(1, 2); s.emplace(5, 6); except that the latter is a bit faster for non-primitives.
 » 6 weeks ago, # | ← Rev. 2 →   +35 \5. Oh god, please don't write any such code ever!This is not 'clean and efficient' code. It's horribly unreadable, especially if you don't use spaces, and a usual if..else construct is as fast as a conditional operator.Instead of this: a&1?a*=2:a+=1; Use this: if(a & 1) { a *= 2; } else { a++; } Or, even better: if(a % 2 == 1) { a *= 2; } else { a++; } This is as fast as a & 1 but (arguably) more readable and more obvious to other code readers.Here's the case when conditional operators actually simplify something. Pretend that you want to calculate 2D prefix sums. Here's how I usually do it: for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { pref[i][j] = ( a[i][j] + (i == 0 ? 0 : pref[i - 1][j]) + (j == 0 ? 0 : pref[i][j - 1]) - (i == 0 || j == 0 ? 0 : pref[i - 1][j - 1]) ); } } Without conditional operators, the code would take more lines, and the +/+/+/- structure wouldn't be as obvious.
•  » » 6 weeks ago, # ^ |   0 In addition: if-else is more convenient for debugging because you can see which branch is it going to.
•  » » 6 weeks ago, # ^ |   0 Why don't you use a 1-indexed 2-D prefix sum, that eradicates the out of bounds issue with case i=0/j=0
•  » » » 6 weeks ago, # ^ |   0 I just want pref to have the same size and indexing as a. Of course, you could make a 1-indexed too but that may require me to modify other algorithms, etc... so I just use 0-indexation everywhere and only fix prefix sums.
•  » » 6 weeks ago, # ^ | ← Rev. 2 →   -14 [DELETED]
•  » » » 6 weeks ago, # ^ |   +5 Conditional operator was not invented for statements, it's for expressions. You shouldn't use a&1 ? a*=2 : ++a, but you may use a = a&1 ? a*2 : a+1. This way you explicitly state the intent: update a variable (a =) depending (?) on some condition (a&1). (as a sidenote, I also hate it when people write if(x) a++,b++; instead of if(x) { a++; b++; })You're right in the second example, code 1 is cleaner than code 2, except that I'd replace (string)"IMPOSSIBLE" with "IMPOSSIBLE"s. Here you use ?: on expressions, not statements, and it works well here. (it'd be even better if C++ could infer the type of n == -1 ? "IMPOSSIBLE" : n expression as std::variant and was able to print it then, but sadly C++ is too strict)
•  » » » » 6 weeks ago, # ^ |   0 You are right.
 » 6 weeks ago, # |   0 U deserve a standing ovation
 » 6 weeks ago, # |   0  auto d = "variable"; // d will become 'string' d will become a const char* (c string) NOT std::string, if you want it to become an std::string you need to use std::string's constructor: string(...) example: auto d = string("variable") 
•  » » 6 weeks ago, # ^ |   0 But then it's just shorter to write string d = "variable"; 
•  » » » 6 weeks ago, # ^ |   0 Yeah exactly
•  » » » » 6 weeks ago, # ^ |   0 And it's also going to create an extra copy
•  » » » » » 5 weeks ago, # ^ | ← Rev. 3 →   0 Hey, I might be wrong, but I have heard that since C++17 in an initialization statement the copy is not created. I mean: string d = "test"; is similar to: string d("test"); As far as I remember, even things like: string d; d = "test"; Are not creating a copy. Since C++17 compiler is smart enough to optimize it. You can read more about it in cppreference or on StackOverFlow
•  » » » » » » 5 weeks ago, # ^ |   0 Oh that's cool, thanks for the information.
 » 6 weeks ago, # |   +31 This blog contains too much fake news and should be removed, because is harmful for inexperienced coders.
•  » » 5 weeks ago, # ^ |   0 The up- and downvote system is supposed to do that. Unfortunatly it does not allways work in the right direction :/
 » 5 weeks ago, # |   +5 This comment section makes me feel like: Cunningham's Law states "the best way to get the right answer on the internet is not to ask a question; it's to post the wrong answer." xDStill I really like these tricks and the comments were very helpful!