Не ну а че, полный курс по С++ - это тема которая зайдет, тем более в твоей подаче. От структурного до ООП, плюс сдл. По пути, конечно, можно рассказывать о твоих насройках/шоткатах/плагинах вима )
На самом деле, если в функцию уже пришёл Type&& не обязательно делать ещё раз std::move, однако если вы используете шаблоны, то, да, Type&& может уже являться универсальной ссылкой
Классный ролик, спасибо вам! Один момент до меня все-таки не доходит: на уровне памяти чем копирование отличается от перемещения? Вот есть вектор объектов типа Т. Мы вызывает метод push_back() и передаем в качестве аргумента rvalue при помощи std::move(), но чтобы новый элемент вектора встал последовательно за предыдущим, его же нужно туда поместить, т.е процессор все равно проделывает работу по размещению в памяти данных. Я думал, что это и есть основное процессорное время на данную операцию. Или же проблема заключается в том, что объект сначала создается на стеке, а потом его нужно еще и скопировать в нужное место? Т.е, перемещая, мы все равно тратим процессорное время на размещения объекта в новых ячейках памяти, но избегаем создания временного объекта на стеке?
разыменование указателя тоже даёт lvalue. Причём указатель - это одна переменная, а результат разыменования это уже другая сущность, которая не имеет имени, но тем не менее lvalue. В этом можно убедиться, посмотрев в cppreference. Опять же функция может возвращать и ссылку и указатель. Таким образом происходит в случае со ссылкой возврат lvalue. Возвращаемый указатель, если я правильно понимаю, это всё-таки rvalue. Спасибо за пояснения.
"R-value" ссылки, наряду с шаблонами - самая сложная концепция языка С++. Поэтому этот ролик самый крутой и полезный. Жаль, что такое интересно только "задротам" и "гикам". Только представьте, насколько упали бы просмотры ИванГая, если бы он начал пилить видео по С++
Спасибо. По этой теме мало доступной информации нашел. К сожалению, в основном статьи на английском. Новичку приходится общую картину рисовать по крупицам. Так понимаю, в функции перемещения требуется снова приводить к rvalue, поскольку параметр функции сам является lvalue с типом правосторонняя ссылка? Т.е. параметр опять дает имя безимянному объекту.
Спасибо. Видео хорошее - в сжатом виде и доступной форме об основах move-семантики. А разрешите маленькую ложечку дегтя?) Думается, что было бы еще нагляднее, если бы в вашем классе Dog data был бы указательным типом. Тогда полезность механизма перемещения стала бы очевиднее. Да и вопрос с обнулением data rvalue-параметра стал бы совсем не праздным.
Вот так, при помощи нехитрого move и амперсандов мы можем сделать из lvalue rvalue. Но зачем? Спасибо за видео, вставка "Есть ли у тебя программа?" шикарная :)
Спасибо). >"Но зачем?" Две клетки в зоопарке: со слоном и львом. А таблички перепутаны. Вопрос: Что легче, поменять животных местами или поменять таблички?)) Вот rvalue нужно, чтобы поменять местами таблички. Может быть, не совсем корректное сравнение, но всё же).
И еще не понятно, зачем нам тогда в функции параметр делать r-v , и передавать с move, если внутри функции он будет l-v и нам там нужно с ним работать как с обычной ссылкой на значение , можно принимать тогда в функции значение по ссылке и в вектор уже перемещать , будет тот же результат но меньше текста , как мне кажется )?
В первом примерно мы передаём по ссылке в функцию и в вектор пушим копию, но если мы в вектор будем тоже передавать через move, разве это не будет одно и тоже ? Что мы преобразуем ссылку в рвелью и переместим в вектор ?
Меня очень интересует вопрос. Недавно я посмотрел урок по c#, где программа дописывала сама себя без перезагрузки процесса или запуска нового процесса. Возможно ли сделать так же на c++?
Мы изучали ядро ОС, дописывали его, изменяли, потом изучали параллельное программирование на Си. Главное, это то, что Вы хотите от этого изучения, что делать потом и что уметь.
В рабочих проектах volatile редко, но встречала, а restrict ни разу :). Исходя из этого, в теории часто спрашивают о них, а на практике не пришлось использовать.
Если я правильно понял, то вы хотите сказать, что при полном понимании и умении применения данных элементов оптимизации, просто не предоставилось корректного случая, точнее возможности корректного использования. Так? Или ответ содержал посыл, что если спросить программиста - он вспомнит что это за "зверь", но в повседневной жизни возможности применения на столько редко попадаются, что о них просто забывают? Это зависит от культуры программирования или от уровня программиста или только от необходимости применения?
Проекты разные, где-то необходимо знать до мелочей одни возможности языка, где-то другие. В зависимости от того, насколько часто Вы применяете что-то, Вы и знаете это "что-то" хорошо или хуже. Я хотела сказать, что это не те квалификаторы, которые мне удалось применить в своей работе). Так что да, от необходимости и частоты применения.
Спасибо за видос! Если std::move используется внутри функции, зачем делать std::move в ее параметрах, если можно просто передать по обычной ссылке? Мне кажется для того что бы видеть, что эта функция забирает владение, или как?
По ссылке push_back в вектор сконструирует копию добавляемого обьекта. Для того, чтобы избежать расходов на копирование исходный объект приводится к типу &&.
Молодец, отлично объясняешь. Единственное, странно объяснять что такое шаблон в контексте данного урока, в эту тему нечего лезть если не знаешь темплейтов) И конечно, как вступление в тему категории значений в с++ неплохо. Но про универсальные ссылки ты упомянула совсем вскользь, про них сделай пожалуйста отдельно видео. Я считаю, заговорив про универсальные ссылки необходимо объяснять про reference folding и про std::forward. И еще можно раскрыть по подробнее исходный код move и forward - там очень интересно)) Если хватит сил можно докопаться до xvalue, pure value, glvalue это тоже интересно по мне) Вообще подача уникальная в рутубе, так держать ты большая молодец, продолжай в том же духе, умничка, респект. С++ как математика, его изучать можно бесконечно))
Спасибо). URef, конечно, заслуживают отдельного видео, там как раз и про *reference collapsing* и про std::forward уместно рассказывать. Всё остальное, что Вы перечислили, вряд ли будет интересно широкой публике, хотя, согласна, вещи увлекательные)).
Жесть, похоже комитет по стандартизации решил специально такой язык сделать, чтоб удобно было на собеседовании каверзные вопросы задавать. О людях кто подумал? (
Сейчас в Джексонвилле обсуждали только C++20, С++23 еще нет. Про запрет указателей - это была первоаперльская шутка четырех иностранных блогеров, и все это перепостили.
Вот один из них: arne-mertz.de/2018/04/raw-pointers-are-gone/ Update 2018-04-02: This post was, of course, an April fool’s joke. Together with four other bloggers we decided to orchestrate a bunch of blog posts about this topic. // Update 2 апреля: Это, конечно, была 1апрельская шутка.
Вот список того, что обсуждали и что будет изменяться в С++20, нет ничего про указатели, по крайней мере, я не нашла:) botondballo.wordpress.com/2018/03/28/trip-report-c-standards-meeting-in-jacksonville-march-2018/#cxx20
Можно вместо std::move использовать static_cast, но есть два важных отличия двух подходов (кроме мелких нюансов): 1. std::move четко показывает, _ЧТО_ Вы хотите сделать (а это важно для тех, кто будет читать Ваш код. Код ведь чаще читается, чем пишется.) 2. Программисты часто ошибаются и вместо && пишут & в static_cast, а с std::move такой досадной ошибки не произойдет. Дополнительным плюсом будет возможность погрепать по коду, где у Вас происходит move, вместо cast.
Оч хотелось бы, чтобы ты подняла вопрос (Java) восходящих и нисходящих преобразований типов классов. Все эти апкасты и даункасты выносят моск. Не понимаю - нафига??? :)
Сылка & -это символьный псевдоним цифрового адреса(так как в компе все память). Указатель * - это ТИПИЗИРОВАННАЯ переменная(с отсчетом ячеек по размеру типа), хранящая адрес типизированной ячейки. Обменять не выделяя память, можно только обменяв адреса на память - это ФАКТ! По логике вещей, отправить псевдоним на псевдоним, означает отправить один и тот же адрес - но это если бы процессор понимал что такое ссылки, а он то знает только адреса. Следовательно, компилятор при линковке, псевдоним на псевдоним, мог бы подсунуть только один и тот же адрес. Таким образом двойная ссылка полный бред. В принципе, отличия ссылки от указателя в том, что ссылка всегда имеет один и тот же адрес, а указатель может иметь любой адрес, но все они типизированные псевдонимы, с отсчетом ячейки по размеру типа, и понимаются только компилятором.
Долго же Вы спали, товарищ)). Двойная ссылка уже 9 лет, как не бред). en.cppreference.com/w/cpp/language/move_constructor en.cppreference.com/w/cpp/utility/move
@@DariaEmacs двойной ссылки нет и не будет, товарищ...))) потому, что это не логично. Есть просто закрепление ячейки памяти при возврате результата, без явного указания псевдонима. А, вы можете называть это ка хотите, это не есть истинное понимания, а просто ограниченная абстракция нагружающая мозг ...))) нужно немножко понимать, что происходит на низком уровне, тогда все будет понятно. Я, же написал, в принципе, отличия ссылки от указателя в том, что ссылка всегда имеет один и тот же адрес, а указатель может иметь любой адрес, но все они типизированные псевдонимы, с отсчетом ячейки по размеру типа, и понимаются только компилятором. Функция это временный объект, и то что она возвращает находится во временной памяти, следовательно, возвращаемый адрес ячейки ПЕРЕМЕННОЙ созданной в функции, освободится после возврата результата, а значит после возврата результата в этой области памяти может быть все что угодно. Это и логично! А, ново введение позволяет неявно фиксировать эту память, вот и все. Пример: int* fooncP(int a, int b) { return new int(a + b); //чтоб вернуть указатель на результат, нужно ячейку зафиксировать //оператором выделения памяти NEW, иначе, так как функция временный объект то и возвращаемое //значение функцией находится во временной памяти, которая освободится после использования //функции, и тем самым по адресу в ячейке может оказаться все что угодно. }