Препоръчвам да проучите <vector>
заглавката на libc++. Ще трябва да се справите с всички неприятни долни черти, които внедряващите std::lib трябва да използват. Но libc++ има реализация, съответстваща на C++11, там за проверка.
оператор за преместване на присвояване
Операторът за присвояване на преместване на контейнер трябва да работи с три отделни възможности:
propagate_on_container_move_assignment
е вярно.
propagate_on_container_move_assignment
е невярно и разпределителите от lhs и rhs се сравняват равни.
propagate_on_container_move_assignment
е невярно и разпределителите от lhs и rhs се сравняват неравномерно.
Когато е възможно, решението между тези три случая трябва да се вземе по време на компилиране, а не по време на изпълнение. По-конкретно, човек трябва да избира между наборите {1} и {2, 3} по време на компилиране, тъй като propagate_on_container_move_assignment
е времева константа на компилиране. Разклоняването по време на компилиране на константа по време на компилиране често се извършва с изпращане на тагове, вместо с if-изявление, както вие шоу.
В нито един от тези случаи не трябва да се използва select_on_container_copy_construction
. Тази функция е само за конструктора за копиране на контейнер.
В случай 1, lhs трябва първо да използва разпределителя на lhs, за да освободи цялата памет, която е била разпределена. Това трябва да се направи първо, защото RHS разпределителят може да не успее да освободи тази памет по-късно. След това разпределителят на lhs се присвоява за преместване от разпределителя на rhs (точно както всяко друго присвояване на преместване). Тогава собствеността върху паметта се прехвърля от контейнера rhs към контейнера lhs. Ако дизайнът на вашия контейнер е такъв, че Rhs контейнерът не може да бъде оставен в състояние без ресурси (лош дизайн imho), тогава нов ресурс може да бъде разпределен от преместения от rhs разпределител за RHS контейнера.
Когато propagate_on_container_move_assignment
е невярно, трябва да изберете между случаи 2 и 3 по време на изпълнение, тъй като сравнението на разпределителя е операция по време на изпълнение.
В случай 2 можете да направите същото като в случай 1, освен не премествайте, задайте разпределителите. Просто пропуснете тази стъпка.
В случай 3 не можете да прехвърлите собственост върху каквато и да е памет от контейнера rhs към контейнера lhs. Единственото нещо, което можете да направите, е сякаш:
assign(make_move_iterator(rhs.begin()), make_move_iterator(rhs.end()));
Имайте предвид, че в случай 1, тъй като алгоритъмът е избран по време на компилиране, value_type
на контейнера не е необходимо да бъде MoveAssignable
или MoveInsertable
(MoveConstructible
), за да преместите-присвоите контейнера. Но в случай 2, value_type
s do трябва да бъдат MoveAssignable
и MoveInsertable
(MoveConstructible
), въпреки че никога не са, защото вие избирате между 2 и 3 по време на изпълнение. И 3 се нуждае от тези операции на value_type
, за да извърши assign
.
Операторът за присвояване на преместване е лесно най-сложният специален член за изпълнение за контейнери. Останалите са много по-лесни:
конструктор за преместване
Конструкторът за преместване просто преместете конструира разпределителя и краде ресурсите от rhs.
конструктор за копиране
Конструкторът на копие получава своя разпределител от select_on_container_copy_construction(rhs.m_alloc)
и след това го използва, за да разпредели ресурси за копието.
оператор за копиране на присвояване
Операторът за присвояване на копие трябва първо да провери дали propagate_on_container_copy_assignment
е вярно. Ако е така и ако разпределителите на lhs и rhs се сравняват неравномерно, тогава lhs трябва първо да освободи цялата памет, защото няма да може да го направи по-късно, след като на разпределителите бъде присвоено копие. След това, ако propagate_on_container_copy_assignment
, копирайте присвояване на разпределителите, в противен случай не го правете. След това копирайте елементите:
assign(rhs.begin(), rhs.end());
person
Howard Hinnant
schedule
14.12.2014