63
\$\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.

(Tips that apply to C as well can be found in Tips for golfing in C - but note that some C tips don't work in C++. For example, C++ does require function prototypes and return values.)

\$\endgroup\$
3
  • 7
    \$\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\$ Commented Apr 21, 2016 at 16:47
  • \$\begingroup\$ @TobySpeight Probably because they have the same url besides the question ID. \$\endgroup\$ Commented Jan 5, 2017 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\$
    – user58988
    Commented Aug 12, 2019 at 21:37

31 Answers 31

29
\$\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\$
3
  • \$\begingroup\$ Replace std::endl with '\n' that saves 5 chars \$\endgroup\$ Commented Mar 24, 2014 at 14:01
  • 8
    \$\begingroup\$ @MukulKumar Well, yes. But for the purposes of demonstrating this tip I left everything except the ternary-conditional un-golfed for clarity. \$\endgroup\$ Commented Mar 24, 2014 at 15:05
  • 7
    \$\begingroup\$ But std::endl isn't "ungolfed", it's just bad style / gratuitous flushing of cout even when that's not needed. endl is the same as << '\n' plus a flush; it's a different layer of stdio that handles conversion from \n to the native platform line ending (e.g. CRLF on DOS) for text streams. If you were golfing or optimizing, you'd put the first \n into the 2nd string literal: "\nSum of evens " \$\endgroup\$ Commented Dec 2, 2019 at 2:58
28
\$\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\$
0
24
\$\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\$
0
21
\$\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\$
2
  • \$\begingroup\$ I wish I could star answers. This is good. \$\endgroup\$
    – S.S. Anne
    Commented Feb 6, 2020 at 18:10
  • 1
    \$\begingroup\$ The stack snippet seems broken \$\endgroup\$ Commented Jul 19, 2022 at 6:50
17
\$\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\$
5
  • 5
    \$\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\$ Commented Sep 11, 2014 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
    Commented Sep 11, 2014 at 11:33
  • 2
    \$\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
    Commented Jul 17, 2019 at 20:29
  • \$\begingroup\$ @celtschk yes, good point. But if you're purely doing the boolean algebra, then it works \$\endgroup\$
    – Baldrickk
    Commented Jul 24, 2019 at 11:03
  • \$\begingroup\$ @S.S.Anne the point is you can use x*y saving a character. \$\endgroup\$
    – Baldrickk
    Commented Feb 7, 2020 at 9:55
15
\$\begingroup\$

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

\$\endgroup\$
13
\$\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\$
1
  • \$\begingroup\$ How about x=1,y=2/*...*/else x++,y++? \$\endgroup\$
    – S.S. Anne
    Commented Feb 6, 2020 at 18:08
13
\$\begingroup\$

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

When using simple if statements:

if(<condition>)<stuff>;

can be changed to:

<condition>?<stuff>:<any single character variable or literal>;

which saves a character.

\$\endgroup\$
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\$
3
  • 2
    \$\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
    Commented Apr 10, 2014 at 19:41
  • 11
    \$\begingroup\$ These two tips would be better placed in two separate answers so they can be voted on individually. \$\endgroup\$ Commented Aug 13, 2014 at 2:53
  • 1
    \$\begingroup\$ What implementations provide these type names? Is there a header you need to include? u8 is probably useful as a 2-byte type name when you don't need large values. \$\endgroup\$ Commented Dec 2, 2019 at 3:01
10
\$\begingroup\$

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

\$\endgroup\$
9
\$\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\$
2
  • 7
    \$\begingroup\$ If you only use a single name, but that quite often, using std::name; may be shorter, though. \$\endgroup\$
    – celtschk
    Commented Apr 10, 2014 at 19:44
  • 19
    \$\begingroup\$ This only saves characters if you use std:: five or more times. \$\endgroup\$
    – user344
    Commented Jun 12, 2014 at 19:00
9
\$\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\$
3
  • \$\begingroup\$ Don't forget you can cut out all that whitespace! (Different tip altogether, but should be mentioned) \$\endgroup\$
    – stokastic
    Commented Sep 11, 2014 at 13:19
  • 2
    \$\begingroup\$ @stokastic The examples aren't meant to be golfed, only to demonstrate how to use the technique. \$\endgroup\$
    – Stuntddude
    Commented Sep 12, 2014 at 2:54
  • 11
    \$\begingroup\$ why not for(int* i=array; i<array+25*25; i++)? Then you only have to keep track of one variable. \$\endgroup\$
    – Lucas
    Commented Aug 13, 2015 at 17:45
9
\$\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\$
8
\$\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
  • 5
    \$\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
    Commented Dec 8, 2017 at 9:47
8
\$\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\$
2
8
\$\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 a byte or two if a is vector or string.

std::sort(a.begin(),a.end());
std::sort(&a[0],&*a.end());

// with using namespace std;
sort(begin(a),end(a));
sort(&a[0],&*end(a));
```
\$\endgroup\$
7
\$\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\$
1
  • 1
    \$\begingroup\$ #import is a deprecated GCC extension. But still is supported by modern versions of GCC. \$\endgroup\$ Commented Dec 2, 2019 at 3:07
7
\$\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\$
6
  • 3
    \$\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\$ Commented Feb 14, 2019 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\$
    – parth_07
    Commented Feb 14, 2019 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\$ Commented Feb 14, 2019 at 10:45
  • 2
    \$\begingroup\$ If you already have a using namespace std, (std::) swap(a,b) is shorter. To avoid #include <algorithm> or <utility>, another answer suggests GCC #import<bits/stdc++.h> to get every C++ header. \$\endgroup\$ Commented Dec 2, 2019 at 3:15
  • 1
    \$\begingroup\$ I don't know why anyone would think +- swaps are the "standard" way, though. You'd never do that outside of code golf, you'd use auto t=a; or something. XOR-swap is the better known no-temporary swap, using just 3 separate ^= statements instead of a b=a-b; that has to name b twice. But yes, you save 4 bytes vs. a^=b;b^=a;a^=b;. I guess you might consider that "standard" in a code-golf context if you don't have any spare variables you can use as a temporary. \$\endgroup\$ Commented Dec 2, 2019 at 3:22
6
\$\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\$
2
  • \$\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
    Commented Sep 28, 2016 at 23:58
  • \$\begingroup\$ Yes possible a+=a--; has Undefined Behaviour \$\endgroup\$
    – user58988
    Commented Jan 28, 2018 at 20:28
6
\$\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\$

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\$
5
\$\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
  • 2
    \$\begingroup\$ When std::list can't be used (usually because you need indexing), std::deque is often usable, saving 1 character per use over std::vector, and still lets you index it. \$\endgroup\$ Commented Mar 7, 2023 at 16:10
5
\$\begingroup\$

It's rather straightforward to cacluate when replacing something with a #define results in shorter code.

#define a blabla

Where a is a single letter name and blabla is the replacement of length \$x\$ has in total \$10+x\$ characters.

If you have \$n\$ times blabla in the code then the #define pays off when

$$10 + x + n < nx$$

With the define you have \$10 + x\$ to define it and \$n\$-times a single character. Without it you have \$n\$-times blabla of length \$x\$. The following table lists how often blabla has to appear given its length for the define to make the code shorter:

\$x\$ \$n\$
2 13
3 7
4 5
5 4

Because the inequality is symmetric, the same table applies when \$n\$ and \$x\$ are swapped, ie if blabla appears \$n = 2\$ times in the code then the define results in shorter code when blabla is of length \$x \ge 13\$. The formula is

$$n > \frac {10 + x} {x - 1}$$

or

$$x > \frac {10 + n} {n - 1}$$

PS: Sometines the single letter named preprocessor symbol has to be followed by a space. This shifts the matters a little towards not using the define, but just a little.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Golf, and nice tip! \$\endgroup\$
    – rydwolf
    Commented Aug 17, 2022 at 20:55
4
\$\begingroup\$

G++ allows for variable-sized arrays, so there is no need to go through the lengthy pointer-malloc-new stuff.

int* array = new int[array_size];

becomes

int array[array_size];

Saves 9 bytes minimum with int.

\$\endgroup\$
4
\$\begingroup\$

Use auto instead of complex type names.

This can be done with generic lambdas and C++20 abbreviated function templates

int x(std::set<std::string>y){}
template<class T>int x(T&y){}
int x(auto&y){}
[](auto&x){}

This also allows you to avoid most includes.

Note that g++ on TIO requires -fconcepts.

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

When writing a full program you can use argc to initialize an integer variable to 1:

main(a){

is the same as:

main(){int a=1;
\$\endgroup\$
1
  • 2
    \$\begingroup\$ this is C, not C++ \$\endgroup\$
    – c--
    Commented Jun 16, 2023 at 18:24
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\$
1
  • 8
    \$\begingroup\$ Instead of int x=(a*10>5)*2-1;, couldn't you do int x=a*10>5?1:-1;, which is 1 byte shorter? \$\endgroup\$
    – girobuz
    Commented Oct 2, 2019 at 23:58
2
\$\begingroup\$

If you have some variables declared in a row :

int a,b,c,d;

You can access b by (&a)[1], or c by (&a)[2] ...

It can be interesting there :

(i?a:i-1?b:i-2?c:d)=k;
VS
(&a)[i]=k;

You could have declared an array a[4], but if you use a, b, c, d in other ways, it's not always interesting to replace b by a[1], c by a[2]

Moreover, you know that x[y] = *(x+y) = y[x], so :

(i?a:i-1?b:i-2?c:d)=k;
VS
(&a)[i]=k;
VS
i[&a]=k;
\$\endgroup\$
1
\$\begingroup\$

If you need a type alias, using is two bytes shorter than #define:

#define T ... // newline
using T=...;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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