Для чего нужна двойная ссылка &&?
Это называется rvalue reference
Ссылка на временный объект.

Прямо (int&& d = 5) используется крайне редко, чтобы продлить время жизни временному объекту.

Куда чаще оно используется в типах возврата (string&& Container::give()), и означает: это ссылка на объект, который спокойно можно выпотрошить. Или в типах параметров — Container& Container::operator = (string&& x): то есть принимает объект, который больше не нужен.

Для чего потрошить объекты? Вот представьте себе код.
std::vector<int> doSmth() {
  std::vector<int> r;
  r.push_back(42);
  return r;
}
...
std::vector<int> a = doSmth();

Забьём на необязательные оптимизации — как эта штука будет действовать по семантике Крестов?
std::vector<int> r; — создадим в стековом фрейме переменную r.
return r; — vector(const vector&) в какое-то место, предложенное вызывающей функцией.
std::vector<int> a = doSmth(); — vector(const vector&) из этого места в a.

Си++17 ТРЕБУЕТ, чтобы подобный возврат гарантированно вызывал ОДИН конструктор копирования (а если конструировать на месте вроде return vector<int>{ 42 }; — то ни одного), но у нас-то Си++03. Не много конструкторов? А ведь зная, что объект больше не нужен, можем просто перенести указатель из одного вектора в другой, точка — даже впрямую, без оптимизаций, никаких перевыделений памяти. Вот этот прямой перенос указателей я и назвал словом «выпотрошить объект».

Пример 1: container = string("alpha") + "bravo"; Тут в контейнер перемещается временная строка.
Пример 2: string a = "alpha"; container = a; Не компилируется: строка a не временная.
Пример 3. container1 = container2.give(); Перенос строки из контейнера в контейнер без выделения памяти.
Пример 4: string a = "alpha"; container = std::move(a); Компилируется (мы функцией move сказали: с обычным объектом обращаться как с временным), но в результате в строке a может быть что угодно и не стоит закладываться на дальнейшее её значение. Но объект после потрошения в любом случае должен быть корректным, ведь ему ещё вызывать деструктор :)

Последний вопрос: кто потрошит? Функция, которая принимает временную ссылку как параметр. В данном случае Container::op=. Чем потрошит? — ну, например, кодом myString=std::move(x) или std::swap(myString, x). А они, в свою очередь — внутренняя string::op= и дружественная swap — прямыми играми с указателями.