53
\$\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\$
  • 5
    \$\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\$ – user58988 Aug 12 '19 at 21:37

27 Answers 27

27
\$\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;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Replace std::endl with '\n' that saves 5 chars \$\endgroup\$ – Mukul Kumar Mar 24 '14 at 14:01
  • 4
    \$\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 --- ex-moderator kitten Mar 24 '14 at 15:05
  • 2
    \$\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\$ – Peter Cordes Dec 2 '19 at 2:58
26
\$\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()
{
  // ...
}
| improve this answer | |
\$\endgroup\$
18
\$\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.

| improve this answer | |
\$\endgroup\$
16
\$\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.

| improve this answer | |
\$\endgroup\$
  • 3
    \$\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
  • 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 Jul 17 '19 at 20:29
  • \$\begingroup\$ @celtschk yes, good point. But if you're purely doing the boolean algebra, then it works \$\endgroup\$ – Baldrickk Jul 24 '19 at 11:03
  • \$\begingroup\$ @S.S.Anne the point is you can use x*y saving a character. \$\endgroup\$ – Baldrickk Feb 7 at 9:55
11
\$\begingroup\$

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

| improve this answer | |
\$\endgroup\$
11
\$\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.

| improve this answer | |
\$\endgroup\$
11
\$\begingroup\$

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

| improve this answer | |
\$\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.)

| improve this answer | |
\$\endgroup\$
  • 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 Apr 10 '14 at 19:41
  • 9
    \$\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
  • \$\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\$ – Peter Cordes Dec 2 '19 at 3:01
9
\$\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.

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

| improve this answer | |
\$\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
  • 1
    \$\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
  • 7
    \$\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
9
\$\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)
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I wish I could star answers. This is good. \$\endgroup\$ – S.S. Anne Feb 6 at 18:10
8
\$\begingroup\$

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

| improve this answer | |
\$\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
  • 14
    \$\begingroup\$ This only saves characters if you use std:: five or more times. \$\endgroup\$ – nyuszika7h Jun 12 '14 at 19:00
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.

| improve this answer | |
\$\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
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

| improve this answer | |
\$\endgroup\$
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.

| improve this answer | |
\$\endgroup\$
5
\$\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;
| improve this answer | |
\$\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\$ – user58988 Jan 28 '18 at 20:28
5
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ #import is a deprecated GCC extension. But still is supported by modern versions of GCC. \$\endgroup\$ – Peter Cordes Dec 2 '19 at 3:07
5
\$\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;
| improve this answer | |
\$\endgroup\$
  • 2
    \$\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 '19 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 '19 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 '19 at 10:45
  • \$\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\$ – Peter Cordes Dec 2 '19 at 3:15
  • \$\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\$ – Peter Cordes Dec 2 '19 at 3:22
5
\$\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!");}
| improve this answer | |
\$\endgroup\$
4
\$\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.

| improve this answer | |
\$\endgroup\$
3
\$\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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\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 Oct 2 '19 at 23:58
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;}
| improve this answer | |
\$\endgroup\$
2
\$\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;}
| improve this answer | |
\$\endgroup\$
1
\$\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));
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

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

| improve this answer | |
\$\endgroup\$
  • 2
    \$\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\$

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;
| improve this answer | |
\$\endgroup\$
0
\$\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.

| improve this answer | |
\$\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.