#cpp #cpp11 #конструктор #семантика
Допустим, у нас есть класс с обычным конструктором: class SomeClass { int size; int *element; public: SomeClass(int i) { //обычный конструктор size = i; element = new int[size]; } }; И предположим, что я добавил туда конструктор копирования и конструктор перемещения (переноса): SomeClass( SomeClass &&other ) { //конструктор перемещения size = other.size; element = other.element; other.size = 0; other.element = nullptr; } SomeClass( SomeClass &other ) { //конструктор копирования size = other.size; element = other.element; other.size = 0; other.element = nullptr; } int main() { SomeClass a1(5); SomeClass a2(a1); //вызов конструктора копирования SomeClass a3 = move(a1); //вызов конструктора переноса } Здесь один нюанс: конструктор копирования не будет копировать, он тоже будет выполнять перенос. В чем тогда отличие? Если фактически происходит одно и тоже. Code::Blocks выдает разницу в секунду. Думаю, тогда вопрос встает между использованием & и &&. Я знаю, что второе - это ссылка на r-value, и что она позволяет обратиться к ресурсам объекта. Но ведь в обоих случая создается новый объект. В чем тогда профит?
Ответы
Ответ 1
Конструктор перемещения это чисто конвенциональная конструкция(так же как и конструктор копирования, собственно), поэтому никто не мешает делать в любом конструкторе всё, что заблагорассудится. Другое дело, что программист, использующий Ваш класс, будет ожидать перемещения от конструктора перемещения и никак не будет ожидать такого подвоха от конструктора копирования. В том числе и поэтому, конструктор копирования всегда объявляется с константным аргументом, а не как у Вас. Ещё раз, конструкторы имеют свои названия исходя из того, что они делают по умолчанию(т.е. тогда, когда их генерирует компилятор). Соответственно, программист тоже должен делать так, как делается по умолчанию, а не придумывать реализацию, которая больше похожа на саботаж, чем на что-либо другое. Исходя из всего вышесказанного: Ваш вопрос не имеет смысла. Отличным примером перемещающего конструктора копирования является std::auto_ptr. Все мы знаем его судьбу.Ответ 2
Существует несколько категорий выражений, наболее известные - это "rvalue" и "lvalue". Переменная с типом T&& может принимать только r-value выражение, переменная с типом T& может принимать только не константные l-value выражения. Совершенно не важно, что это за переменная - агрумент конструктора или нет. Соответственно разница между SomeClass( SomeClass &&other ) и SomeClass( SomeClass &other ) - только в том, что первый будет вызываться только для r-value выражений, а второй - только для неконстантных l-value выражений. При этом ни один из них не может принимать const SomeClass &. Что именно делают конструкторы - никому не важно, то что у них одинаковый код - это тоже не важно. Единственное отличие - это категории выражений, которые они могут принимать.Ответ 3
Ваш конструктор копирования изменяет состояние объекта, с которого делается копия. Соответственно, такую операцию уже нельзя в полной мере назвать копированием. Правильная сигнатура конструктора копирования такая: SomeClass( const SomeClass &other )Ответ 4
В чем тогда профит? Rvalue ссылки позволяют программистам избегать логически ненужного копирования и обеспечивать возможность идеальной передачи (perfect forwarding). Прежде всего они предназначены для использования в высоко производительных проектах и библиотеках.
Комментариев нет:
Отправить комментарий