47
\$\begingroup\$

What general tips do you have for golfing in C++? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to C++ (e.g. "remove comments" is not an answer). Please post one tip per answer.

\$\endgroup\$
  • 4
    \$\begingroup\$ Many of the tips for golfing in C are also applicable to C++, so please assume that readers are familiar with that question; only post here if you have something that isn't also a valid C golfing tip. \$\endgroup\$ – Toby Speight Apr 21 '16 at 16:47
  • \$\begingroup\$ @TobySpeight Probably because they have the same url besides the question ID. \$\endgroup\$ – NoOneIsHere Jan 5 '17 at 19:22
  • \$\begingroup\$ C and C++, even if not 'golfing' type, are right and easy (if one consider the right subset of C++) \$\endgroup\$ – RosLuP Aug 12 at 21:37

25 Answers 25

23
\$\begingroup\$

The ternary conditional operator ?: can often be used as a stand in for simple if--else statements at considerable savings.

It is of special value in that it can be used to select alternate lvalues as in

#include <iostream>
#include <cstdlib>
int main(int c, char**v){
  int o=0,e=0,u;
  while(--c) ((u=atoi(v[c]))%2?o:e)+=u;
  std::cout << "Sum of odds " << o <<std::endl
            << "Sum of evens " << e <<std::endl;
}
\$\endgroup\$
  • \$\begingroup\$ haven't run the code yet, but I don't think it works the way you say. ((u=atoi(v[c]))%2?o:e)+=u does nothing but to add the value u to the expression on the left which gets the value o or e, but the variables o and e remain unchanged so they will always be 0. check the code to see what hapens. you should use adresses to make it work \$\endgroup\$ – Bogdan Alexandru Oct 4 '12 at 10:09
  • 4
    \$\begingroup\$ @BogdanAlexandru Er...do run it. It really does work. The value of the parenthetical expression is a reference to one or the other of e and o. Note that this is different from how this operator works in c where this trick does not work because it can not be an lvalue. \$\endgroup\$ – dmckee Oct 4 '12 at 13:03
  • \$\begingroup\$ Replace std::endl with '\n' that saves 5 chars \$\endgroup\$ – Mukul Kumar Mar 24 '14 at 14:01
  • 3
    \$\begingroup\$ @MukulKumar Well, yes. But for the purposes of demonstrating this tip I left everything except the ternary-conditional un-golfed for clarity. \$\endgroup\$ – dmckee Mar 24 '14 at 15:05
20
\$\begingroup\$

Sometimes you can save two characters by using the fact that static storage duration variables (that especially includes all global scope variables) are automatically zero-initialized at the beginning (unlike automatic variables where you have no such guarantee). So instead of

int main()
{
  int a=0;
  // ...
}

you can write

int a;
int main()
{
  // ...
}
\$\endgroup\$
14
\$\begingroup\$

Some compilers (e.g. GCC) support multi-character constants. This can save a few characters when a large integer value is required. Example:

int n='  ';

The value is implementation-specific. Usually the value of 'ab' is 256*'a'+'b' or 'a'+256*'b'. You can specify up to 4 characters between the quotation marks.

\$\endgroup\$
  • 3
    \$\begingroup\$ GCC? You mean g++? \$\endgroup\$ – Nathan Osman Feb 20 '11 at 22:01
  • 6
    \$\begingroup\$ @George Edison: GCC stands for the GNU Compiler Collection, which encompasses all its frontends, including those for C, C++, Go, etc. \$\endgroup\$ – Joey Adams Apr 26 '11 at 2:01
  • \$\begingroup\$ @Joey: I know, but it's also the name of the GNU C Compiler. \$\endgroup\$ – Nathan Osman Apr 26 '11 at 16:21
  • 24
    \$\begingroup\$ @George: The GNU C compiler is called gcc, not GCC. \$\endgroup\$ – fredoverflow Jul 20 '11 at 17:12
  • \$\begingroup\$ Might as well remember that, I could forget. \$\endgroup\$ – user54200 Jul 5 '16 at 15:05
10
\$\begingroup\$

Use the following types:

u64, s64, u32, s32 (or int)

For repetitive words/types, use #defines:

#define a while

It's only worth it if you use while a lot to make up for the extra 10 characters. (About 4.)

\$\endgroup\$
  • 1
    \$\begingroup\$ The types u64, s64, u32 and s32 are not part of C++. They may be a non-standard extension of your compiler (I've never ever seen them, though). \$\endgroup\$ – celtschk Apr 10 '14 at 19:41
  • 4
    \$\begingroup\$ These two tips would be better placed in two separate answers so they can be voted on individually. \$\endgroup\$ – trichoplax Aug 13 '14 at 2:53
10
\$\begingroup\$

One that I found handy:

Taking advantage of the fact that non-zero values evaluate to true in boolean expressions, and that x&&y evaluates to x*y when dealing with booleans

(x!=0 && y!=0)

evaluates to

(x*y)

You just have to be aware of overflows, as pointed out below.

\$\endgroup\$
  • 2
    \$\begingroup\$ Technically, it's x!=0 && y!=0. But when using multiplication you need to be careful with overflows. When using 32-bit integers x = y = 65536 (and several other combinations of powers of two) would also yield x*y = 0. \$\endgroup\$ – Martin Ender Sep 11 '14 at 11:15
  • \$\begingroup\$ Yes, that's right. I used it as a twodimensional array bounds check here: codegolf.stackexchange.com/a/37571/31477 where that didn't matter. I'll edit those points in. \$\endgroup\$ – Baldrickk Sep 11 '14 at 11:33
  • 1
    \$\begingroup\$ Note however that && has a short-circuit behaviour which * lacks. For example, you can't replace i++!=0&&j++!=0 with i++*j++. \$\endgroup\$ – celtschk Jul 17 at 20:29
  • \$\begingroup\$ @celtschk yes, good point. But if you're purely doing the boolean algebra, then it works \$\endgroup\$ – Baldrickk Jul 24 at 11:03
9
\$\begingroup\$

If you're willing to use C++0x, you can use new features like lambdas.

\$\endgroup\$
9
\$\begingroup\$

When possible, change && and || to & and | respectively.

When using simple if statements:

if(<condition>)<stuff>;

can be changed to:

<condition>?<stuff>:<any single letter variable>;

which saves a character.

\$\endgroup\$
8
\$\begingroup\$

Instead of using while(1), use for(;;), saving one character :)

\$\endgroup\$
8
\$\begingroup\$

Using the comma operator in lieu of open and close braces can save a few characters, if you have a situation where your clauses have more than one statement in them:

if(c){x=1;cout<<"Hi";y=2;}else{x=2;cout<<"Bye";y=3;}

vs.

if(c)x=1,cout<<"Hi",y=2;else x=2,cout<<"Bye",y=3;###

Two characters saved on a plain IF, or three total for an IF/ELSE.

As a point of distinction between C and C++, the result of a comma expression in C++ as a whole may be used as an lvalue...FWIW.

\$\endgroup\$
7
\$\begingroup\$

Since array elements are stored directly after one another in memory, instead of something like this:

for(int x = 0; x < 25; x++) {
    for(int y = 0; y < 25; y++)
        array[x][y] = whatever;
}

You can do something like this:

int* pointer = array;
for(int i = 0; i < 25*25; i++, pointer++)
    *pointer = whatever;

Obviously neither of the above are golfed, for readability, but explicitly using pointers can save you a lot of space.

\$\endgroup\$
  • \$\begingroup\$ Don't forget you can cut out all that whitespace! (Different tip altogether, but should be mentioned) \$\endgroup\$ – stokastic Sep 11 '14 at 13:19
  • \$\begingroup\$ @stokastic The examples aren't meant to be golfed, only to demonstrate how to use the technique. \$\endgroup\$ – Stuntddude Sep 12 '14 at 2:54
  • 6
    \$\begingroup\$ why not for(int* i=array; i<array+25*25; i++)? Then you only have to keep track of one variable. \$\endgroup\$ – Lucas Aug 13 '15 at 17:45
5
\$\begingroup\$

Quite an obvious one, but it you are using a lot of the standard library, using namespace std; might save a few characters.

\$\endgroup\$
  • 5
    \$\begingroup\$ If you only use a single name, but that quite often, using std::name; may be shorter, though. \$\endgroup\$ – celtschk Apr 10 '14 at 19:44
  • 9
    \$\begingroup\$ This only saves characters if you use std:: five or more times. \$\endgroup\$ – nyuszika7h Jun 12 '14 at 19:00
5
\$\begingroup\$

It is useful to remember is that a[i] is the same as *(a+i).

Replace a[0] with *a for two character savings. Also, a[i][0] is equivalent to *a[i] and a[0][i] shrinks down to i[*a]. So if you are hard-coding a 0 index in your array, a better way probably exists.

\$\endgroup\$
5
\$\begingroup\$

Instead of writing big powers of 10, use e notation. For example, a=1000000000 is longer than a=1e9. This can be extended to other numbers like a=1e9+24 is better than a=1000000024.

\$\endgroup\$
  • 1
    \$\begingroup\$ Note that this is not exactly equivalent, need to cast to integer types before using. For example 1e9/x is not the same as 1000000000/x or int(1e9)/x. \$\endgroup\$ – user202729 Dec 8 '17 at 9:47
5
\$\begingroup\$

You may use the ternary operator ?: without any expressions in the true-block (it saves a byte)

#include <iostream>

int foo()
{
    std::cout << "Foo\n";
}

int main()
{
    1?foo():0;  // if (true) foo()
    0?:foo();   // if (!false) foo()
}

Check it here

\$\endgroup\$
5
\$\begingroup\$

Shorter header

This is GCC specific, it may be extensible to other compilers.

Precompiled header.

In G++ bits/stdc++.h is the precompiled header consists of all other headers. If you need to import 2 different ones you can just use this.

Shorter header.

This is all headers listed on http://en.cppreference.com/w/cpp/header:

$("#a").text(pako.inflate(atob('eJx9VkuW1DAM3HON2cOGx4o3V8lzK0q3wZ9gy90TTo+dDKCyM710yT9VqWS/2ECuzPzdhO3108vfUeCHGmUWNfJmVSMbsxo5m/VUEutZjaWsTo9NSkYfO/OvouNZDP1U4xqFOHkjNzVORmzU8YXDXcf5ym86lSIwvljBXOmWYtA7evYxbXCEi0aAAl930TM4JdiDSLYV0njQzSQNlA7Ikmy4KuDOJDFB6mGOHoVZHrPeNMsM7LhIBuWQ6C1pvW6Jjd5jKVKSXtII/qwlaIoA0EoAgHYPZy+A2GswDhCWH37tVpmkKShinZWtmzPzomkyyZoAika/GkiBRsUaU7jK5MxJULNexUGkdpaDAgvFcwKKq2Eqx1q4OCDLgOQBsdGbYIGxQV+KM9NdnmvRsgK99vIFZC95QPbSAmSvYEAeA0Jy7QxMNsdvX789RdoFbVh0Jce1+r6roHoYRXC/Fa4NAlxzN67vQXbk/xAfrn7UDEI73UjLXsUI7aXek1cru4dqIQ8Uh4H1Kl4HtRrseB8kpbEyDylg1sH84N1LjG6QY4bNqN604dpU/Ea8y4QJHLAm211jsnLzsJapDGvTaIsduBTdAt5TxTTOsCaDq+rg/Vq2WPwl0FBteQs02tY6zlsWBp++MzNUQDsaG2edNkky2JsOgae7xRe6brA3b9x2P3yqBoaiX2J6mDRP3WOdq2N4nvo3sYSYZm4RfBr/4/ghOF7IKXGOJRFD6lZszfM3p+FsimvdybhmIrQov621ZXoOYtwX/KVACG8BIbw4hPoPSwyzbepO+8txgfYJC/uvCgT7fwgGu08IBPsfEgSH3whEh7cZ6ek/LshQ/3RBdPhsQHR80yA8PtMQPmndqPhpO9Bpn7msI+bEsSfp96ZCYU7diOec+wpPOrckMvaBsz6Y9KS6//Xcp3f62LHdZu9NeFqjs7S9/gHXxXg4'), {to: 'string'}));
<script src="https://cdn.rawgit.com/nodeca/pako/master/dist/pako.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="a">
  
</pre>

sorted in increasing order of length.

Some of them are already longer than bits/stdc++.h, and some of them requires C++17 support. Some others are not supported by TIO G++ (for reasons I don't know of). Filter out them we have:

$("#a").text(pako.inflate(atob('eJx9VcuS3CAMvOc39p5Tak+p/MoUI2SbhIcDYrz++4BdW6WG1B7VYI36IebNRfLV8s/Ix69vb59VYVFVMLuqXCqq8q7oqyQusKql7l7XJmdzqtry36rPixj6o+p2CucUjGyqzkZc0ucLx5c+55U/NJUqUD+dIFfacoq6Y+CQ8gk/4ZMRkCC0LvoG5ww9iOTcgcZBm8kaqANQJLu4KuDFJCkD9WhTQGOWw+qmRSyo4xMZtENScKT92jIb3WOpUrP+pAv8XVvQHQGgRwCAPod3T0DcGo0HhOV32IevTNYSVHHeyTncsbxoZHajqxDBY1MKZ0E/RocmAyiFlmUdnlgDZ5CvLUPTT5uSJmSZkDIhLgUTHagxeUfJMr3ka507K/DiiiYgV5wBuWIDyJVOQI4JIVmH5SRX0vuP9y+RPqCLi06pE25rDVl/GT++HG5W9rYVhrrTgNAlJBK+sofQFdBRlpbHEWrxm8SLk57NlgHq6RoUncyiOXO3yHDr1nTauGdKfhLaQjNqk3Zcrwt/EO/tUY1I4Ia12H5N2ckWkNUc7gt4VljSmxaO/D+sS+6bEzhLZ4YRrpH6yPCifHKbPOwN8cFq1x6SDb4b5SzC4dEWBqK4pHyYbB/DH19p68D2cf+//APa+54V'), {to: 'string'}));
<script src="https://cdn.rawgit.com/nodeca/pako/master/dist/pako.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="a">
  
</pre>

It may happens that some of them can be replaced by shorter ones. Just binary search whether the one you need can be replaced. In particular:

cstdio -> ios        (-3 bytes)
algorithm -> regex   (-4 bytes)
vector -> queue      (-1 byte)
string -> map        (-3 bytes)
bitset -> regex      (-1 byte)
numeric -> random    (-1 byte)
\$\endgroup\$
4
\$\begingroup\$

#import instead of #include gives you one more byte.

Also, the space character between #import and header is not necessarily:

#include <map>
// vs
#import<map>

And if you need something from stdlib header, you may import any header with STL container (preferable set or map) instead of cstdlib.

\$\endgroup\$
3
\$\begingroup\$

Arithmetic operations on Booleans:

Although

a*=b>0?.5:-.5

is better than

if(b>0)a*=.5;else a*=-.5;

it is not as good as

a*=(b>0)-.5

Also, using #define on anything that is used a lot. It is often shorter than using functions, since type names are not necessary.

Combine things as much as possible:

a+=a--;

is the same as

a=2*a-1;
\$\endgroup\$
  • \$\begingroup\$ While your examples are correct, be careful of invoking undefined behavior when using x as an lvalue and x++ as an rvalue. undefined behavior and sequence points \$\endgroup\$ – ceilingcat Sep 28 '16 at 23:58
  • \$\begingroup\$ Yes possible a+=a--; has Undefined Behaviour \$\endgroup\$ – RosLuP Jan 28 '18 at 20:28
3
\$\begingroup\$

Use generic lambdas as cheap templates

For types other than int, using them as function arguments can be expensive. However, generic lambdas were introduced (in C++14?) and allow any lambda to be a template - using auto for the argument types can save bytes. Compare:

double f(double x, double y)
[](auto x, auto y)

Generic lambdas are also very convenient for accepting iterators - probably the best way to accept array inputs in C++ is [](auto a, auto z), where a and z are passed as begin() and end() of the array/vector/list/etc.

\$\endgroup\$
2
\$\begingroup\$

In my first attempt at code golf for task "Subtract the next numbers" I have started from function (58 bytes)

int f(int N, int P){int F;for(F=N;P;F-=++N,P--);return F;}

then safe 5 bytes with shifting to lambda and moving initialization out of for (53)

[](int N,int P){int F=N;for(;P;F-=++N,P--);return F;}

and finally after switching from for to while I got 51 bytes:

[](int N,int P){int F=N;while(P--)F-=++N;return F;}

The ungolfed test code is something like:

#include <iostream>
int main(void)
{
    int N, P;
    std::cin >> N >> P;
    auto f = [](int N,int P)
    {
        int F = N;
        while (P--)
            F -= ++N;
        return F;
    };
    std::cout << f(N, P) << std::endl;
    return 0;
}

UPDATE:

Actually for can reach the same length as while:

[](int N,int P){int F=N;for(;P--;F-=++N);return F;}
\$\endgroup\$
2
\$\begingroup\$

Kind of late to the party I guess...

If you want to turn an expression into -1 and 1 instead of 0 and 1, instead of this:

int x;
if (a * 10 > 5)
    x = 1;
else
    x = -1;

do this:

int x = (a * 10 > 5) * 2 - 1;

It can save some bytes depending on usage.

\$\endgroup\$
2
\$\begingroup\$

If you want to swap two integer variables a and b then ,

a^=b^=a^=b;

can be used , saving 5 characters than the standard way

a+=b;
b=a-b;
a-=b;
\$\endgroup\$
  • 1
    \$\begingroup\$ About that standard way. ,t at the ints created earlier and then t=a;a=b;b=t; would have already been 3 bytes shorter than the a+=b;b=a-b;a-=b;. Still, your a^=b^=a^=b; is even shorter than that, so +1 from me. I don't know C++, but it indeed works. As a Java code-golfer I'm sad it doesn't seem to work there. :( \$\endgroup\$ – Kevin Cruijssen Feb 14 at 9:34
  • 1
    \$\begingroup\$ @KevinCruijssen Yeah , I should have mentioned C++ , I dont know java much , but a^=b;b^=a;a^=b; is working fine in java . \$\endgroup\$ – joker007 Feb 14 at 10:33
  • 1
    \$\begingroup\$ No need to explicitly mention C++. All these tips are for C++. :) As a Java developer I was just curious if something similar could be done in Java, but apparently not. a^=b;b^=a;a^=b; indeed works, but is longer than the ,t+t=a;a=b;b=t;. Sorry about mentioning Java, since it's off-topic here. But nice tip for C++ codegolfers! \$\endgroup\$ – Kevin Cruijssen Feb 14 at 10:45
1
\$\begingroup\$

If you're doing C++11 or newer (which should always be the case now), use auto for complex types, if possible.

Example: 54 Bytes instead of 66

#include<vector>
std::vector<int> f(std::vector<int> l){return l;}
#include<vector>
auto f(std::vector<int> l){return l;}

Also, as performance does not matter, for some challenges a std::list may just do the job for a few bytes less:

#include<list>
auto f(std::list<int> l){return l;}
\$\endgroup\$
1
\$\begingroup\$

Use GCC builtins instead of importing

If you are using a GCC compiler, it sometimes helps to use their builtin functions, such as __builtin_puts or __builtin_clz. For example,

44 bytes:

int main(){__builtin_puts("Hello, world!");}`

50 bytes:

#import<cstdio>
int main(){puts("Hello, world!");}
\$\endgroup\$
0
\$\begingroup\$

Don't use string(""), use "". It saves 8 bytes.

\$\endgroup\$
  • \$\begingroup\$ It's not exactly equivalent. For example "" + 'a' is char* + char, which is pointer addition, while std::string("") + 'a' is std::string + char - string concatenation. string() would work. \$\endgroup\$ – user202729 Dec 8 '17 at 9:49
0
\$\begingroup\$

Functions in <algorithm> often requires passing a.begin(),a.end() which is really long, instead you can use &a[0],&*end(a) to save 3 bytes if a is vector or string.

sort(a.begin(),a.end());
sort(begin(a),end(a));
sort(&a[0],&*end(a));
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.