My initial thought:
myvec.reserve(myvec.size()*3); //reserve not only speeds things upt it also protects us ftom iterator invalidation
vector::iterator it = myvec.end(); //we ant to add two times the origional onto the end so we save the end of the origional end
myvec.insert(myvec.end(), myvec.begin(), it);
myvec.insert(myvec.end(), myvec.begin(), it);
thanks to Emilio Garavaglia for first pointing out problems with this, see here many reasons why this has problems: Does std::vector::insert() invalidate iterators if the vector has enough room (created through reserve)?
Second try:
std::size_t size = myvec.size();
myvec.resize(size*3); //resize must protects us from iterator invalidation
vector::iterator it = myvec.begin()+size;
std::copy(myvec.begin(),it,it);
std::copy(myvec.begin(),it,it+size);
since no implementation is going to implement a std::string whos default constructor allocates something on the heap this should cause less heap access and therefore be faster than others examples.
Another heap access minimization is to copy the vector into another insert it and then move in the originals, I stole Emilio Garavaglia code and pimped it:
{
vector m = { "a", "b" };
auto n = m; // keep initial value safe
m.reserve(3 * m.size()); // preallocate, to avoid consecutive allocations
m.insert(m.end, n.begin(), n.end());
std::for_each(n.begin(),n.end(),[&n](std::string &in){n.emplace_back(std::move(in));});
}