HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Теги: copy/move elision, универсальные ссылки</p>
1 <p>Теги: copy/move elision, универсальные ссылки</p>
2 <p>Copy/move elision представляет собой оптимизацию, когда компилятор может убрать определенные вызовы конструктора копирования и деструктора, но только при возврате объекта из функции и если тип возвращаемого объекта совпадает с типом функции.</p>
2 <p>Copy/move elision представляет собой оптимизацию, когда компилятор может убрать определенные вызовы конструктора копирования и деструктора, но только при возврате объекта из функции и если тип возвращаемого объекта совпадает с типом функции.</p>
3 <p>В результате при возврате из функции применение<a>std::move()</a>способно понизить производительность, ограничив тем самым компилятор в Copy elision оптимизации, ведь отсутствие конструктора, по сути, быстрее, чем конструктор перемещения.</p>
3 <p>В результате при возврате из функции применение<a>std::move()</a>способно понизить производительность, ограничив тем самым компилятор в Copy elision оптимизации, ведь отсутствие конструктора, по сути, быстрее, чем конструктор перемещения.</p>
4 <p>В данном случае std::move() лишь замедляет код, добавляя излишний вызов String(String&amp;&amp; other) и ~String(). При этом стоит учесть, что в C++20 copy/move elision может быть расширен, в результате чего в ряде случаев применение std::move() тоже снизит производительность.</p>
4 <p>В данном случае std::move() лишь замедляет код, добавляя излишний вызов String(String&amp;&amp; other) и ~String(). При этом стоит учесть, что в C++20 copy/move elision может быть расширен, в результате чего в ряде случаев применение std::move() тоже снизит производительность.</p>
5 <h2>Универсальные ссылки</h2>
5 <h2>Универсальные ссылки</h2>
6 <p>Вернувшись к теме одной из<a>предыдущих статей</a>, скажем, что универсальные ссылки способны быть как rvalue-, так и lvalue-ссылкой - это зависит от аргументов либо результата функции. Применяются они в шаблонах и в auto&amp;&amp;:</p>
6 <p>Вернувшись к теме одной из<a>предыдущих статей</a>, скажем, что универсальные ссылки способны быть как rvalue-, так и lvalue-ссылкой - это зависит от аргументов либо результата функции. Применяются они в шаблонах и в auto&amp;&amp;:</p>
7 <p>На основе данного шаблона компилятор генерирует две функции, причем одна из них принимает lvalue, а вторая - rvalue, если они будут применяться. Когда разработчик желает использовать перемещение для rvalue-ссылки и обычное простое копирование для lvalue-ссылки, он может применить std::forward(), приводящий свой аргумент к rvalue лишь тогда, когда его тип - это rvalue-ссылка. Что касается std::forward(), то он требует явного указания шаблонного параметра.</p>
7 <p>На основе данного шаблона компилятор генерирует две функции, причем одна из них принимает lvalue, а вторая - rvalue, если они будут применяться. Когда разработчик желает использовать перемещение для rvalue-ссылки и обычное простое копирование для lvalue-ссылки, он может применить std::forward(), приводящий свой аргумент к rvalue лишь тогда, когда его тип - это rvalue-ссылка. Что касается std::forward(), то он требует явного указания шаблонного параметра.</p>
8 <p>Собственно говоря, универсальная ссылка просто обязана быть шаблонным параметром, откуда в нашем примере и взялось странное определение шаблона функции в формате T&amp;&amp;. Таким образом, std::vector&lt;T&gt;&amp;&amp; - это уже не универсальная ссылка, а rvalue-ссылка.</p>
8 <p>Собственно говоря, универсальная ссылка просто обязана быть шаблонным параметром, откуда в нашем примере и взялось странное определение шаблона функции в формате T&amp;&amp;. Таким образом, std::vector&lt;T&gt;&amp;&amp; - это уже не универсальная ссылка, а rvalue-ссылка.</p>
9 <p>Но вообще, особой разницы между универсальной и rvalue-ссылкой не существует. Можно сказать, что универсальная ссылка является лишь удобной абстракцией над rvalue-ссылкой, которой, как раз таки, многие и пользуются. Но как же тогда rvalue-ссылка превращается в lvalue-ссылку, имея lvalue-аргумент? Ответ - путем свертывания ссылок.</p>
9 <p>Но вообще, особой разницы между универсальной и rvalue-ссылкой не существует. Можно сказать, что универсальная ссылка является лишь удобной абстракцией над rvalue-ссылкой, которой, как раз таки, многие и пользуются. Но как же тогда rvalue-ссылка превращается в lvalue-ссылку, имея lvalue-аргумент? Ответ - путем свертывания ссылок.</p>
10 <p>Когда происходит вызов template_func(string), компилятор генерирует следующий заголовок функции:</p>
10 <p>Когда происходит вызов template_func(string), компилятор генерирует следующий заголовок функции:</p>
11 <p>Таким образом, получается ссылка на ссылку! Сделать так вручную невозможно, однако шаблоны могут. Потом компилятор свертывает ссылку на ссылку, а происходит это по определенному правилу: результатом свертывания становится rvalue-ссылка, но лишь в том случае, если обе ссылки - это rvalue-ссылки. И, как раз из-за данного безобразия и проще применять абстракцию универсальных ссылок.</p>
11 <p>Таким образом, получается ссылка на ссылку! Сделать так вручную невозможно, однако шаблоны могут. Потом компилятор свертывает ссылку на ссылку, а происходит это по определенному правилу: результатом свертывания становится rvalue-ссылка, но лишь в том случае, если обе ссылки - это rvalue-ссылки. И, как раз из-за данного безобразия и проще применять абстракцию универсальных ссылок.</p>
12 <p><em><a>Источник</a></em></p>
12 <p><em><a>Источник</a></em></p>
13  
13