Обновить
65
12
Дмитрий Пономарев@dm_frox

Программист

Отправить сообщение

Вообще надо различать вывод аргумента шаблона и вывод типа параметра функции. Они могут не совпадать, типа параметра функции может быть украшен спецификатором ссылки, const и другими модификаторами. В шаблонах функций аргумента шаблона нам доступен, но в лямбдах с auto он будет скрытым.

Спасибо за конструктивную критику.

А вот использовать ссылку в качестве параметра функции безопасно

Здесь я имел в виду передача ссылки в глубину стека, конечно возврат этой же ссылки может все сломать и я про это писал.

И про "ссылку" получаемую из итератора std::vector<bool> ...

Согласен, что итераторы, возвращающие прокси-объекты, не обсуждал. Эта тема подробно обсуждается у Скотта Мейерса.

Не сказано так же о том, что взятие ссылки на временный объект продлевает его срок жизни до конца жизни самой ссылки.

Не согласен, этому посвящен раздел 4.1.

Одна из идей, которой руководствуются при проектировании ссылок – это сделать ссылку максимально неотличимой от объекта, на который она ссылается. Этим можно объяснить, почему при инициализации C++ ссылки не используется специальный оператор (типа & в случае указателей) и не используется оператор разыменования (типа * в случае указателей) для доступа к объекту. В результате возникают некоторые коллизии, но небольшие, например, нельзя перегрузить функции, у которых параметр передается по значению и по ссылке на константу.
Теперь про неизменяемость C++ ссылок, то есть отсутствие нулевых ссылок (обязательная инициализация) и невозможность перенаправить на другую переменную. Посмотрим, какие изменения в языке нужны, если бы ссылки были изменяемые, то есть допускали нулевое значение и перенаправление на другую переменную. Первая проблема – это как быть с присваиванием. Нужно отличать присваивание самих ссылок и присваивание объектов, на которые она ссылается. Для изменяемых ссылок логично реализовывать присваивание как присваивание самих ссылок (а как иначе организовать перенаправление?), но присваивание объектов тоже очень важно в C++. Вторая проблема – это использование самих ссылок в качестве выходного параметра (это еще один вариант реализовать перенаправление). Для этого надо было бы разрешить указатели на ссылку и ссылку на ссылку. Решение всех этих проблем усложнило бы и без того непростой C++, то есть неизменяемость C++ ссылок позволило не переусложнить язык.
Теперь посмотрим, что происходит в языках со сборкой мусора, например C#. Объекты, управляемые сборщиком мусора, доступны только через ссылку, таким образом, никаких коллизий между объектом и ссылкой на него быть не может, не нужен оператор разыменования. Ссылки на объекты, управляемые сборщиком мусора, являются изменяемыми, то есть могут быть нулевыми и при присваивании происходит присваивание самих ссылок. Но при этом сами объекты не поддерживают присваивание, для них нельзя перегрузить оператор =, поэтому коллизий не возникает. Если для объекта требуется операция, аналогичная копированию или присваиванию, то в C# надо реализовать специальные методы, типа IClonable.Clone(). Но потребность в таких операциях возникает крайне редко. Ссылки на объекты, управляемые сборщиком мусора, сами могут быть выходными параметрами функции, для таких параметров при объявлении и вызове надо использовать ключевое слово ref.

И я тоже. И [VJG] тоже (с развернутой аргументацией). Здесь мы имеем дело с старыми сишными правилами, которые действительно многих раздражают. Я сам долго думал, как с этим быть, и решил все-таки остановится на каноническом синтаксисе, хотя в своих проектах я его не использую.

В [VJG] forwarding reference переводится как передаваемая ссылка, и мне кажется по смыслу это больше подходит, английские отглагольные определения не всегда можно так просто перевести. А к универсальной ссылке все (включая меня) привыкли благодаря Скотту Мейерсу.

Проблема в том что термин "ссылка" применяется очень широко и, соответственно, имеет разный смысл в разных контекстах. Указатель - это тоже ссылка, если трактовать его в широком смысле. В C++ ссылка (reference) имеет вполне конкретное и достаточно узкое значение.

Да, const T&& не может быть универсальной ссылкой. Но я решил не обсуждать rvalue ссылки на константу, статья и так чрезмерно большая. Согласен, что можно придумать для них применение, но чем-то надо жертвовать.

Спасибо! Вопросы интересные, но не простые, с ходу ответить не могу. Подробнее напишу немного позднее.

Согласен, что в C#, Jave термин "ссылочный тип" имеет совсем другой смысл. Но в C++ шаблонах нужно как то называть тип самой ссылки, а не тип переменой, на которую она ссылается, без этого описание шаблонов невозможно. Посмотрите Вандевурд, Дэвид, Джосаттис, Николаи М., Грегор, Дуглас. Шаблоны C++. Справочник разработчика, 2-е изд. В этом справочнике как раз для этого и используется термин "ссылочный тип", так что я ничего не придумывал. Вот цитата

std::is_reference<T>::value

Дает true, если T представляет собой ссылочный тип.

Не соглашусь с Вами. Ссылочный тип - это отдельный тип, но вторичный или производный, то есть образованный от другого типа (как и тип массива). Это хорошо видно, если использовать ссылочный тип в качестве аргумента шаблона, например std::pair<int&, int&>. Ссылочный тип в некотором смысле ущербный, об этом я много писал. А тип переменной, на которую ссылка ссылается - это совсем другое. Здесь мы имеем проблему скорее относящуюся к русскому языку в котором подобные вещи не очень удобно различать. Это примерно тоже, что и разница между константным указателем и указателем на константу.

Попробовал многое из описанного, VS2019 версия 16.10.0. Действительно Microsoft молодец, почти все реализовано. std::format почти 1 к 1 как в C#. По поводу некоторых других фич возникает вопрос: почему такие простые и нужные вещи появились только сейчас (std::numbers::pi, std::string::starts_with()).
Впечатляет. Теперь все эти фичи надо попробовать на уровне семплов, а когда это войдет в повседневную практику, не вполне ясно. Лично я сейчас неплохо ориентируюсь в C++17, но применяю его фичи не часто. Похоже многие руководители не горят желанием переходить на современные версии компиляторов, объясняя это необходимостью совместимости со старыми стандартами. Например в VS2019 по умолчанию C++14, а C++17 и последний стандарт надо включать специально. Правда на днях было обновление до 16.10.0 в котором C++20 поддерживается ощутимо лучше.
Определять полный набор операторов сравнения для пользовательских типов приходится очень редко. Обычно определяют < для сортировки и set или == и хеш для хеш таблиц. Особого восторга эта фича не вызвала.
Спасибо, что обратили внимание. Вообще автоопределение типа по списку в фигурных скобках может дать сюрпризы, здесь правила несколько запутанны. Например массив нельзя объявить auto, я писал об этом. Надо каждый раз проверять, что результат будет ожидаемый. Ну а печалится, что std::array побитово не совпадает с массивом, по моему, не стоит. Мы не должны программировать полагаясь на знание внутренней структуры объекта, мы должны использовать только интерфейс.
Спасибо! Сейчас вспоминаю, что и я когда-то с такими штучками сталкивался, правда довольно давно.
Это иллюстрация довольно известного совета — никогда не работайте с массивами в полиморфном стиле, через базовый класс.
Попробовал в MSVS 2019 standard C++17.
struct S
{
	int x;
	int z[];
};

Действительно компилируется, предупреждение Warning C4200 nonstandard extension used: zero — sized array in struct / union
Но память под такой массив не выделяется. Попытка доступа компилируется, но при выполнении ошибка: выход за границу стека. При попытке сделать такую структуру базовой или членом возникает ошибка. Не понятно, как это можно использовать (ну может быть только в union).
Спасибо! Честно говоря не знал. Но _countof() MinGW тоже поддерживает.
Спасибо! Рад, что формат понравился. Надеюсь через пару недель будет еще статья. Действительно пользовательские new/delete используются редко (лично я сам никогда). Но мне хотелось закрыть тему про перегрузку в C++ и без пользовательские new/delete это бы не получилось.
Я бы включил эти вопросы в статью про тривиальные типы и неинициализированные переменные. Тема на самом деле довольно интересная, правда материала не очень много, так на пару страниц.

Информация

В рейтинге
619-й
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Зарегистрирован
Активность