Adding arbitrarily long integers C++ (string represented) I'm working through some Project Euler problems using C++ and some of the numbers in question are starting to get quite large (21000 for Problem 16) and I need to add some of these large numbers together, so I quickly threw together a string represented (positive) integer adder:

#include &lt;vector&gt;
#include &lt;string&gt;

std::string AddStringNumbers(std::string n1, std::string n2) {
    while (n1.length() &lt; n2.length()) {
        n1 = "0" + n1;
    }
    while (n2.length() &lt; n1.length()) {
        n2 = "0" + n2;
    }

    std::vector&lt;int&gt; sums = std::vector&lt;int&gt;(n1.length(), 0);
    for (int i = 0; i &lt; n1.length(); i++) {
        sums[i] = (n1[i] - '0') + (n2[i] - '0');
    }

    for (int i = sums.size() - 1; i &gt; 0; i--) {
        while (sums[i] &gt; 9) {
            sums[i] -= 10;
            sums[i - 1] += 1;
        }
    }
    if (sums[0] &gt; 9) {
        sums.insert(sums.begin(), 0);
        while (sums[1] &gt; 9) {
            sums[1] -= 10;
            sums[0] += 1;
        }
    }

    std::string o = "";
    for (int i = 0; i &lt; sums.size(); i++) {
        o += (char)('0' + sums[i]);
    }
    return o;
}


Once this was implemented, the solution was simple:

int Problem016(int n) {
    std::string num = "1";
    for (int64_t i = 0; i &lt; n; i++) {
        num = AddStringNumbers(num, num);
    }

    int sum = 0;
    for (int i = 0; i &lt; num.length(); i++) {
        sum += num[i] - '0';
    }
    return sum;
}


Called with:

Problem016(1000);


Is there anything that I can do to improve my AddStringNumbers function? I'm especially interested in the use of storage types other than std::string and what the advantages of doing so would be. It should also be noted that I do have an intention of doing something like this in a class however, as this was quickly thrown together for the solution that's parked for the time being.

I'm less interested in my method of solving Problem 16, however any comments on that would also be appreciated.
Prepending zeros one at a time is quite inefficient.  It could be improved by making a string of the appropriate length in one go:

{
    auto l1 = n1.length();
    auto l2 = n2.length();
    if (l1 &lt; l2)
        n1 = std::string{"0", l2-l1} + n1;
    else if (l1 &gt; l2)
        n2 = std::string{"0",  l1-l2} + n2;
}


Reassembling the string afterwards character by character is also inefficient.  This can be improved by telling the string how long it will need to be:

std::string o = "";
o.reserve(sums.size());


The index variables i should be an unsigned type to compare against string length or vector size - I recommend using the same type as those methods return.

Greater gains can be made by keeping the long integer as a chain of digits without adding '0' to make them printable characters at each stage; it also helps to store them in little-endian order (so that any carry gets appended rather than prepended).  See Digit-by-digit addition using vectors for a start.  You could reduce storage requirements by using base-100 instead of base-10 (char is guaranteed to hold ranging at least from 0 to 127).