C++ code to sort a list of elements
#include&lt;iostream&gt;
#include&lt;vector&gt;
#include&lt;random&gt;
#include&lt;chrono&gt;


Leave some space between the #includes and the rest of your code, that's easier to read. Besides, I really like &lt;chrono&gt; myself too, but you don't seem to use it afterwards.

using namespace std;
using namespace std::chrono;


using directives for a whole namespace is a bad idea. You risk conflicts between the names defined in std (and there's quite a lot of them) and those you define yourself. Safety is worth a few more keystrokes.

vector&lt;int&gt; merge(vector&lt;int&gt; a,vector&lt;int&gt; b){


That function signature means you're passing a and b by value, that is to say you copy the argument vectors. It might be the good move sometimes, but here it isn't, because you only read them. So const std::vector&lt;int&gt;&amp; a, const std::vector&lt;int&gt;&amp; b is better.

    int i=0;
    int j=0;


i, j, why not? but it doesn't scream what you'll be using those variables for.

    vector&lt;int&gt; result;
    while(i&lt;a.size()&amp;&amp;j&lt;b.size()){


I would rather use iterators in the first place (I mean, in the function's signature), because:


it avoids comparison issues (vector.size() is unsigned, whereas i and j are signed) 
it makes it easier to write and use generic code
it allows you to merge sequences which are only a part of a container, or even inside the same container.

if(a[i]&lt;b[j]){



There's a trick here: if a[i] == b[j] you'll insert b[j] first. It might be innocuous -it is for an int- but programmers expect that min(a, b) will return a if a == b. Since a sorting algorithm is a good candidate for abstraction (a vector of strings is sorted the same way as a vector of ints or floats), you should respect that rule.

        result.push_back(a[i]);
        i++;


Unless you need to keep track of the old value, use pre-incrementation (++i) since i++ creates and returns a temporary value.

        }
        else{
            result.push_back(b[j]);
            j++;
        }
    }
    while(i&lt;a.size()){
        result.push_back(a[i]);
        i++;
    }
    while(j&lt;b.size()){
        result.push_back(b[j]);
        j++;
    }


copy and paste is an anti-pattern. Standard algorithms will provide what you need in a more elegant way, especially if you use iterators: std::copy(current_a, a.end(), std::back_inserter(result));

    return result;
}

vector&lt;int&gt; mergesort(vector&lt;int&gt; a,int low,int hi){
    vector&lt;int&gt; b,c,result;
    if(low==hi)
        return {a[hi]};
    b=mergesort(a,low,(low+hi)/2);
    c=mergesort(a,(hi+low)/2+1,hi);
    result=merge(b,c);
    return result;
}


This part is all right, even if I believe you should try to reduce the place you need to merge-sort or at least the number of allocations.

int main(){

    std::random_device rd; // obtain a random number from hardware
    std::mt19937 eng(rd()); // seed the generator
    std::uniform_int_distribution&lt;&gt; distr(0,90); // define the range
    vector &lt;int&gt; num;
    for(int i=0;i&lt;30;i++)
        num.push_back(distr(eng));    
    vector&lt;int&gt; a=mergesort(num,0,num.size()-1);
    for(auto &amp;i:a)


You generally don't take integers by reference (a reference is the size of or bigger than an int, and you don't take non-const references when you don't modify the variable, which you don't.

        cout&lt;&lt;i&lt;&lt;" ";  
}