
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.143.211.215] |
![]() |
|
![]() |
Сообщ.
#1
,
|
|
Ок. У меня есть крутой класс complex_number. Покажи примерную схему, как мне его реализовать, чтобы в него легко можно было передавать и float, и class cool_real_number_having_long_mantissa_with_great_exponent.
Добавлено Ну как бы да. Это как раз то, что выше я обозвал "любой тип можно сделать ссылочным". Нужны значения, не используем &, нужна ссылочность, используем. Я этим легко управляю. Добавлено T и является, разве нет? Добавлено Цитата D_KEY @ Тогда ссылочных типов в Плюсах не было бы. Были бы простые модификаторы типа передачи параметров.Вот ссылки в C++ мне совсем не нравятся. Иногда даже думаю, не лучше ли бы было, если бы они не являлись самостоятельными типами, а были просто спецификаторами для параметров функции/возвращаемого значения Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#2
,
|
|
|
Указатель?
Добавлено Цитата Qraizer @ Не совсем понимаю, что именно тебе нужно. Но подозреваю, что это делается аналогично плюсам. Например, специализацией перегруженных операторов. Ок. У меня есть крутой класс complex_number. Покажи примерную схему, как мне его реализовать, чтобы в него легко можно было передавать и float, и class cool_real_number_having_long_mantissa_with_great_exponent. Добавлено Цитата Qraizer @ При присваивании ссылоки другой ссылке T не копируется, а при присваивании "обычной" переменной копируется. То есть значение зависит от контекста.T и является, разве нет? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#3
,
|
|
|
Ну вот я про это и говорил. В языке с "чистой" семантикой значений есть проблема с тем, чтобы определить функцию разыменования. Но тут, как мне кажется, достаточно было бы спецификаторов. ![]() ![]() ref int foo(int *x) { return *x; } ref int - это не тип, тип тут int. ref - способ передачи/возврата. Цитата Тогда ссылочных типов в Плюсах не было бы. Были бы простые модификаторы типа передачи параметров. Вот я не понимаю, так ли это плохо... Добавлено Цитата applegame @ Указатель? И какие операции над "значениями" типа ссылки я могу делать? Да у ссылки даже размера нет ![]() Добавлено Цитата applegame @ Вряд ли, не помню когда это было. А в последнее время как-то не возникало необходимости в ссылках. У ссылки в плюсах есть серьезное отличие от указателя: ссылка требует обязательной инициализации, то бишь без специальных ухищрений ссылка не может ссылаться на несуществующий объект (уничтожение объекта после создания ссылки не учитываем), а вот указатель может указывать на null или вообще в случайное место. Это отдельная тема. Некий nullable/option/maybe нужен. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#4
,
|
|
|
Цитата D_KEY @ И какие операции над "значениями" типа ссылки я могу делать? Да у ссылки даже размера нет А никаких. И не должен мочь, к слову. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#5
,
|
|
|
Цитата Flex Ferrum @ Почему никаких? А копирование?А никаких. И не должен мочь, к слову. ![]() ![]() void foo(int& x) { int& y = x; // какая операция здесь происходит? } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#6
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ И какие операции над "значениями" типа ссылки я могу делать? Да у ссылки даже размера нет А никаких. И не должен мочь, к слову. Тогда зачем ссылки в языке в качестве типов? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#7
,
|
|
|
Цитата D_KEY @ Ну, де-факто он есть и равен размеру указателя.Да у ссылки даже размера нет ![]() https://glot.io/snippets/ergz7vqc42 Хз как оно в стандарте описано, implementation specific? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#8
,
|
|
|
applegame, возьми sizeof, попробуй сделать массив ссылок.
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#9
,
|
|
|
В D, кстати, "указатель" на класс размер как раз таки имеет и он равен размеру указателя, что сам по себе еще тот WAT:
https://glot.io/snippets/ergzfr193j Цитата D_KEY @ Да, я знаю, что это невозможно:applegame, возьми sizeof, попробуй сделать массив ссылок. Цитата СтандартЪ There shall be no references to references, no arrays of references, and no pointers to references. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#10
,
|
|
|
Цитата D_KEY @ Тогда зачем ссылки в языке в качестве типов? Ты меня расстраиваешь. Ссылка - это не отдельный тип, а модификатор типа. Точно так же как const или volatile. ![]() ![]() Добавлено Ссылочный тип в C++ - это способ задать синоним переменной. Что будет под капотом этого синонима в данном конкретном месте программы - решает компилятор. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#11
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ Тогда зачем ссылки в языке в качестве типов? Ты меня расстраиваешь. Ссылка - это не отдельный тип, а модификатор типа. Точно так же как const или volatile. ![]() ![]() Добавлено Ссылочный тип в C++ - это способ задать синоним переменной. Что будет под капотом этого синонима в данном конкретном месте программы - решает компилятор. Не вижу тут ответа на мой вопрос ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#12
,
|
|
|
Цитата D_KEY @ Не вижу тут ответа на мой вопрос Ещё раз. Ссылка - это не отдельный тип (как, например, std::reference_wrapper). Это модификатор имеющегося типа. Поэтому сложно дать ответ на вопрос, который поставлен некорректно. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#13
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ Не вижу тут ответа на мой вопрос Ещё раз. Ссылка - это не отдельный тип (как, например, std::reference_wrapper). Это модификатор имеющегося типа. Поэтому сложно дать ответ на вопрос, который поставлен некорректно. Хорошо. Зачем ссылки в языке в качестве модификатора типа? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#14
,
|
|
|
Цитата D_KEY @ Зачем ссылки в языке в качестве модификатора типа? Затем, чтобы была возможность создавать алиасы для объектов. Не указатели на объекты, которые ведут себя как объекты-значения, а полноценные алиасы, которые обрабатываются компилятором так, как он считает нужным. Работая со ссылкой ты всегда работаешь с оригинальным объектам. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#15
,
|
|
|
Цитата Flex Ferrum @ То бишь ссылка это просто красявый синтаксис для разыменованного указателя.Затем, чтобы была возможность создавать алиасы для объектов. Не указатели на объекты, которые ведут себя как объекты-значения, а полноценные алиасы, которые обрабатываются компилятором так, как он считает нужным. Работая со ссылкой ты всегда работаешь с оригинальным объектам. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#16
,
|
|
|
Цитата applegame @ То бишь ссылка это просто красявый синтаксис для разыменованного указателя. Нет, нет, и ещё раз нет. Откуда вообще пошла эта дурь с тем, что ссылка - это синтаксический сахар для разыменованного указателя? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#17
,
|
|
Цитата Flex Ferrum @ Нет, нет, и ещё раз нет. Откуда вообще пошла эта дурь с тем, что ссылка - это синтаксический сахар для разыменованного указателя? В чём разница? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#18
,
|
|
Цитата applegame @ Нет, это указатели лишённые основных своих минусов.То бишь ссылка это просто красявый синтаксис для разыменованного указателя. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#19
,
|
|
|
Цитата OpenGL @ В чём разница? В том, что ссылка может (под капотом) стать указателем только в определённых случаях. Например, при передаче в функцию, принимающую ссылку. Но если ты в одной области видимости объявишь объект и ссылку на него, то ссылка указателем не станет, ибо в этом нет необходимости. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#20
,
|
|
|
Цитата Flex Ferrum @ Это все внутрикомпиляторные дела. Компилятор запросто может и разыменованный указатель соптимизировать и не создавать реальной переменной. А может и ссылку создать в виде указателя, если ему приспичит. Это не агрумент:В том, что ссылка может (под капотом) стать указателем только в определённых случаях. Например, при передаче в функцию, принимающую ссылку. Но если ты в одной области видимости объявишь объект и ссылку на него, то ссылка указателем не станет, ибо в этом нет необходимости. ![]() ![]() void foo(int& x) { int& y = x; y = 2; int* z = &x; z = 2; } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#21
,
|
|
Цитата applegame @ Ну это-то понятно. Естественно cool_real_number_having_long_mantissa_with_great_exponent их все имеет. Вопрос в том, как мне complex_number писать. Метакодом я могу напроксить себе какие-нибудь assgn() с нужными if (is(...)) и вместо =, но что-то для меня это как-то костыльно смотрится.Не совсем понимаю, что именно тебе нужно. Но подозреваю, что это делается аналогично плюсам. Например, специализацией перегруженных операторов. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#22
,
|
|
|
Цитата applegame @ Это все внутрикомпиляторные дела. Компилятор запросто может и разыменованный указатель соптимизировать и не создавать реальной переменной. А может и ссылку создать в виде указателя, если ему приспичит. Это не агрумент. Где-то в стандарте написано, что ссылка - это такой своеобразный вариант указателя? Насколько я знаю, нет. И не может быть написано. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#23
,
|
|
Цитата Flex Ferrum @ В том, что ссылка может (под капотом) стать указателем только в определённых случаях. Например, при передаче в функцию, принимающую ссылку. Но если ты в одной области видимости объявишь объект и ссылку на него, то ссылка указателем не станет, ибо в этом нет необходимости. Это вопрос оптимизаций. Поведение-то фактически эквивалетно поведению указателя, который автоматически разыменовывается. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#24
,
|
|
|
Цитата OpenGL @ Это вопрос оптимизаций. Это не вопрос оптимизаций, это вопрос семантики. Объявление ссылки не порождает самостоятельную сущность (в отличие от указателя). Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#25
,
|
|
Я не вижу тут иную семантику, отличную семантики указателя
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#26
,
|
|
|
Цитата Qraizer @ Понятно, о чем ты говоришь. В таких случаях в D используются структуры, которые передаются по значению.Ну это-то понятно. Естественно cool_real_number_having_long_mantissa_with_great_exponent их все имеет. Вопрос в том, как мне complex_number писать. Метакодом я могу напроксить себе какие-нибудь assgn() с нужными if (is(...)) и вместо =, но что-то для меня это как-то костыльно смотрится. Если же твой cool_real_number_having_long_mantissa_with_great_exponent не простой класс, а скажем абстрактный базовый, то тебе всяко придется передавать его по указателю, а значит придется городить тот же метакод из разных оверлоадов. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#27
,
|
|
Цитата applegame @ В общем случае не может. Даже больше: может в ограниченном количестве случаев. Всё потому, что указатель доступен программисту как есть, поэтому компилятор не может гарантировать, кто где-то, в невидимом ему контексте, этот указатель программером не поменяется, даже если всё время жизни объекта-указателя у него перед глазами.Компилятор запросто может и разыменованный указатель соптимизировать и не создавать реальной переменной. А может и ссылку создать в виде указателя, если ему приспичит. Если интересно и ещё не в курсе, почитай в гугле на тему "pointer aliasing". Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Которые доступны при замене указателей на ссылки, т.к. единственное место, где ссылка может поменять своё значение – это точка её инициализации. Конечно, невелика разница, если рассматриваемый объект является параметром функции/метода, но достаточно представить себе поле класса, и тут уже не всё так шоколадно с указателями и всё прекрасно с ссылками. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#28
,
|
|
|
Цитата Flex Ferrum @ Неверно, порождает. Ведь можно создать переменную ссылочного типа - это вполне конкретная сущность, то что компилятор решил ее соптимизировать в пустоту - это личное дело его оптимизатора. Настоящий алиас присутствует в D. Вот он реально не создает никаких рантайм сущностей, в отличие от плюсовых ссылок:Это не вопрос оптимизаций, это вопрос семантики. Объявление ссылки не порождает самостоятельную сущность (в отличие от указателя). ![]() ![]() void foo(alias a)() { a++; } void bar() { int a = 10; foo!(a); assert(a == 11); } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#29
,
|
|
Цитата applegame @ Это ещё почему? Т.е. я не могу структуру рассматривать как неPOD, что ли?В таких случаях в D используются структуры, которые передаются по значению. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#30
,
|
|
|
Цитата Qraizer @ Да. Но ведь то же самое относится и к ссылке.В общем случае не может. Даже больше: может в ограниченном количестве случаев. Всё потому, что указатель доступен программисту как есть, поэтому компилятор не может гарантировать, кто где-то, в невидимом ему контексте, этот указатель программером не поменяется, даже если всё время жизни объекта-указателя у него перед глазами. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#31
,
|
|
Цитата applegame @ Но ведь то же самое относится и к ссылке. Э-э-э, ты внимательно прочитал? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#32
,
|
|
Цитата applegame @ Настоящий алиас присутствует в D. Вот он реально не создает никаких рантайм сущностей, в отличие от плюсовых ссылок: А как он работает? Правильно я понимаю, что он требует передать то, что является именем переменной, и поэтому в данную функцию нельзя передать, например, разыменованный указатель? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#33
,
|
|
|
Цитата applegame @ Ведь можно создать переменную ссылочного типа - это вполне конкретная сущность Можно объявить. Но память под неё выдеяться не будет (как под указатель) далеко не всегда. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#34
,
|
|
|
Цитата Qraizer @ Структуры в D умеют тоже, что и классы, кроме традиционного наследования. То бишь это не совсем POD, так как конструкторы и деструкторы могут быть нетривиальными. Логика такова: если объект полиморфный, то его всяко придется передавать по указателю, если же нет, то полиморфное наследование не нужно и можно применять обычные структуры. Зачем они так сделали? Не спрашивайте, я не знаю. Мне это тоже не очень нравится, но на практике особо не мешает.Это ещё почему? Т.е. я не могу структуру рассматривать как неPOD, что ли? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#35
,
|
|
|
Цитата applegame @ Да. Но ведь то же самое относится и к ссылке. Нет. И именно потому, что ссылка не является самостоятельной сущностью. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#36
,
|
|
|
Цитата Flex Ferrum @ Ну тоесть в этом плане отличий от указателя нет, так как память под указатель тоже может не выделится. Может будет выделяться, а может нет. Если ссылка - член класса, то память однозначно будет выделяться, как и под указатель. Можно объявить. Но память под неё выдеяться не будет (как под указатель) далеко не всегда. Добавлено Цитата Flex Ferrum @ Я полагаю, что это implementation defined. А то у тебя получается, что ссылка то является самостоятельной сущностью, то не является. В зависимости от контекста и прихоти компилятора.Нет. И именно потому, что ссылка не является самостоятельной сущностью. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#37
,
|
|
Цитата Flex Ferrum @ Цитата applegame @ Ведь можно создать переменную ссылочного типа - это вполне конкретная сущность Можно объявить. Но память под неё выдеяться не будет (как под указатель) далеко не всегда. А вот можно пример, когда, при равнозначном коде, память под указатель должна выделиться, а под ссылку - нет? ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#38
,
|
|
|
Цитата applegame @ Цитата Flex Ferrum @ Ну тоесть в этом плане отличий от указателя нет. Может будет выделяться, а может нет. Если ссылка - член класса, то однозначно будет. Можно объявить. Но память под неё выдеяться не будет (как под указатель) далеко не всегда. Добавлено Цитата Flex Ferrum @ Я полагаю, что это implementation defined. А то у тебя получается, что ссылка то является самостоятельной сущностью, то не является. В зависимости от контекста и прихоти компилятора.Нет. И именно потому, что ссылка не является самостоятельной сущностью. Как раз таки под указатель память будет выделена всегда. И это отличие - фундаментальное. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#39
,
|
|
|
Цитата Flex Ferrum @ Затем, чтобы была возможность создавать алиасы для объектов. Так зачем? Если верить D&E, то ссылки появились ради перегрузки операторов ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#40
,
|
|
|
Цитата OpenGL @ В этой функции alias - это вообше параметр шаблона. Передается compile-time, и передать туда разыменованный указатель действительно нальзя, потому что адрес неизвестен compile-time. А как он работает? Правильно я понимаю, что он требует передать то, что является именем переменной, и поэтому в данную функцию нельзя передать, например, разыменованный указатель? Добавлено Цитата Flex Ferrum @ Правда? - https://godbolt.org/g/TPkoRt Как раз таки под указатель память будет выделена всегда. И это отличие - фундаментальное. Добавлено Цитата Qraizer @ Да. Потому что упомянутый тобой pointer aliasing в плюсах относится не только к указателям, но и к ссылкам.Э-э-э, ты внимательно прочитал? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#41
,
|
|
|
а ссылка на указатель - *& - есть в D?
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#42
,
|
|
|
Цитата _lcf_ @ Да:а ссылка на указатель - *& - есть в D? ![]() ![]() ![]() void foo(ref int* s) { s++; } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#43
,
|
|
|
а если в качестве возвращаемого значения - какой-нибудь нуль(птр/опт/ещекакаянибудьбдня) можно вернуть, или только указатель на объект, который кажет в нульптр?
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#44
,
|
|
|
Цитата applegame @ Правда? Правда. Вот смотри. Код: ![]() ![]() void Refs1() { volatile int a = 10; volatile int& b = a; volatile int* c = &b + 1; printf("%d", a); printf("%d", b); printf("%p", c); } Превращается в итоге в такое вот чудо: ![]() ![]() .file 3 "no_refs.cpp" .loc 3 5 0 .cfi_startproc sub rsp, 56 .seh_stackalloc 56 .cfi_def_cfa_offset 64 .seh_endprologue .loc 3 6 0 mov DWORD PTR 44[rsp], 10 .LVL3: .loc 3 10 0 mov edx, DWORD PTR 44[rsp] lea rcx, .LC0[rip] call _ZL6printfPKcz .LVL4: .loc 3 11 0 mov edx, DWORD PTR 44[rsp] lea rcx, .LC0[rip] call _ZL6printfPKcz .LVL5: .loc 3 12 0 lea rdx, 48[rsp] .LVL6: lea rcx, .LC1[rip] call _ZL6printfPKcz nop .LVL7: .loc 3 13 0 add rsp, 56 .cfi_def_cfa_offset 8 ret .cfi_endproc Добавлено Компиляция с ключами -std=c++17 и -O1. Обрати внимание на строчки 12, 17 и 22. Как можешь заметить, в 12 и 17 идёт обращение к одной и той же области памяти. Если сделать волатильным ещё и сам указатель, то для него будет выделена отдельная ячейка: ![]() ![]() .file 3 "no_refs.cpp" .loc 3 5 0 .cfi_startproc sub rsp, 56 .seh_stackalloc 56 .cfi_def_cfa_offset 64 .seh_endprologue .loc 3 6 0 mov DWORD PTR 44[rsp], 10 .LVL3: .loc 3 8 0 lea rax, 48[rsp] mov QWORD PTR 32[rsp], rax .loc 3 10 0 mov edx, DWORD PTR 44[rsp] lea rcx, .LC0[rip] call _ZL6printfPKcz .LVL4: .loc 3 11 0 mov edx, DWORD PTR 44[rsp] lea rcx, .LC0[rip] call _ZL6printfPKcz .LVL5: .loc 3 12 0 mov rdx, QWORD PTR 32[rsp] lea rcx, .LC1[rip] call _ZL6printfPKcz nop .LVL6: .loc 3 13 0 add rsp, 56 .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE1546: Добавлено (строка 13 и 25) Добавлено А для ![]() ![]() printf("%d", *c); будет сгенерированно: ![]() ![]() .LVL5: .loc 3 12 0 mov rax, QWORD PTR 32[rsp] mov edx, DWORD PTR [rax] lea rcx, .LC0[rip] call _ZL6printfPKcz Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#45
,
|
|
|
Цитата Flex Ferrum @ И что я в этом коде должен увидеть? Вот более приятный для просмотра вид:Превращается в итоге в такое вот чудо: https://godbolt.org/g/XSBcn3 И тут я не вижу выделения памяти ни под ссылку ни под указатель. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#46
,
|
|
|
Вот что рожает gcc 7.1 -O3 для
![]() ![]() printf("%p", c); ![]() ![]() .LC0: .string "%d" .LC1: .string "%p" Refs1(): sub rsp, 24 mov edi, OFFSET FLAT:.LC0 xor eax, eax mov DWORD PTR [rsp+12], 10 mov esi, DWORD PTR [rsp+12] call printf mov esi, DWORD PTR [rsp+12] mov edi, OFFSET FLAT:.LC0 xor eax, eax call printf lea rsi, [rsp+16] mov edi, OFFSET FLAT:.LC1 xor eax, eax call printf add rsp, 24 ret Меняем на ![]() ![]() printf("%p", *c); И видим, что изменилась ровно одна строка, что в общем то и ожидалось: ![]() ![]() .LC0: .string "%d" .LC1: .string "%p" Refs1(): sub rsp, 24 mov edi, OFFSET FLAT:.LC0 xor eax, eax mov DWORD PTR [rsp+12], 10 mov esi, DWORD PTR [rsp+12] call printf mov esi, DWORD PTR [rsp+12] mov edi, OFFSET FLAT:.LC0 xor eax, eax call printf mov esi, DWORD PTR [rsp+16] ;было lea rsi, [rsp+16] mov edi, OFFSET FLAT:.LC1 xor eax, eax call printf add rsp, 24 ret И что я тут должен увидеть? GCC создал одну переменную a на стеке, после чего соптимизировал в пустоту и ссылку и указатель и лезет и за тем и за другим напрямую туда где лежит a. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#47
,
|
|
|
applegame, ты должен там увидеть (и увидишь) что указатель есть (rsp+16), а ссылки - нет.... При обращении по ссылке он лезет в переменную (rsp+12).
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#48
,
|
|
|
Сообщ.
#49
,
|
|
|
Цитата Flex Ferrum @ Ты ошибаешься.applegame, ты должен там увидеть (и увидишь) что указатель есть (rsp+16), а ссылки - нет.... При обращении по ссылке он лезет в переменную (rsp+12). (rsp + 16) - это не указатель, это адрес переменной a плюс единица: (rsp + 12 + sizeof(int)) == rsp+16 Замени "&b + 1" на "&b + 2" и (rsp+16) поменяется на (rsp+20): https://godbolt.org/g/j39jBP Там только одна переменная - (rsp+12). Для указателя и ссылки GCC не выделил память. На самом деле на сайте это и так видно. Строки с объявлением указателя и ссылки имеют белый цвет, а это значит, что для них не сгенерировано никакого кода. Они соптимизированы полностью. Добавлено Цитата D_KEY @ Это потому что Флекс почему-то уверен, что в реализации ссылок и указателей есть какая-то принципиальная разница. Хотя это уже второй пример, когда выделение памяти под указатель не происходит.Что-то вы в реализацию ушли. То есть, вот это утверждение уже дважды опровергнуто, даже volatile не помогает: Цитата Flex Ferrum @ Как раз таки под указатель память будет выделена всегда. И это отличие - фундаментальное. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#50
,
|
|
|
Да это вопрос оптимизации и кодогенерации. Меня же волнует система типов. Я пока не вижу толк от того, что ссылки это часть именно системы типов.
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#51
,
|
|
|
Сообщ.
#52
,
|
|
|
Цитата Flex Ferrum @ Нет, нету. Тут у тебя ссылка и указатель в неравных условиях. Волатильную ссылку создать нельзя в отличие от указателя. В итоге ты просто, грубо говоря, запертил оптимизировать указатель, а ссылку не запретил. Отключи оптимизацию вообще и для ссылки тоже будет выделена память.Угу. Есть. А так я могу легко заставить выделить память под твою ссылку даже с оптимизацией: https://godbolt.org/g/sNgSPX Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#53
,
|
|
|
Цитата applegame @ Волатильную ссылку создать нельзя в отличие от указателя. В итоге ты просто, грубо говоря, запертил оптимизировать указатель, а ссылку не запретил. Что и требовалось доказать. ![]() ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#54
,
|
|
|
Цитата applegame @ Волатильную ссылку создать нельзя в отличие от указателя и указатель на ссылку нельзя, а ссылку на указатель можно. значит, таки есть отличия?! ![]() ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#55
,
|
|
|
Цитата Flex Ferrum @ А это и не требовалось доказать. Очевидно, что ссылки - это не указатели. Но область применения ссылок полностью перекрывается указателями. То бишь без ссылок обойтись можно, а вот без указателей уже нет. Можно сказать, что ссылки - это эдакие сильно ограниченные указатели с автоматическим разыменованием. Если ты сам себе запретишь делать с указателями то, что запрещено делать со ссылками, то разница между ними исчезнет (кроме синтаксиса).Что и требовалось доказать. ![]() ![]() А вообще мы говорим об одном и том же, но с разных сторон. С точки зрения реализации можно сказать, что ссылка - это указатель, с логической же точки зрения это не указатель, а алиас. Но для чистоты алиаса не хватает запрета на фокусы, вроде ссылок на объекты из кучи. Цитата _lcf_ @ и да, хватит тут чирикать, ответьте на мой вопрос, гуру D ![]() Если ты про это Цитата _lcf_ @ То я не понял вопроса. Объясни нормальным птичьим языком. а если в качестве возвращаемого значения - какой-нибудь нуль(птр/опт/ещекакаянибудьбдня) можно вернуть, или только указатель на объект, который кажет в нульптр? ![]() Типа если функция возвращает ссылку, то можно ли вернуть ссылку содержащую null? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#56
,
|
|
|
Цитата applegame @ Объясни нормальным птичьим языком. ну что-то типа такого: ![]() ![]() some_class *class_normal; some_class *class_int; some_class *class_log; some_class *class_empty = nullptr; ... some_class *&foobar::get_class_for_mode(some_class_enum_mode mode) { switch (mode) { case some_class_enum_mode::NORMAL: return class_normal; break; case some_class_enum_mode::INTEGER: return class_int; break; case some_class_enum_mode::LOGARITHMIC: return class_log; break; case some_class_enum_mode::UNDEFINED: case some_class_enum_mode::COUNT: break; } return class_empty; //TODO mmm, not good idea?! } ну если про использование, то дальше что-то типа: ![]() ![]() for (auto t : enum_range (some_class_enum_mode::COUNT)) { some_class *&sc = get_class_for_mode (some_class_enum_mode(t)); if (sc) { //TODO do something with sc } } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#57
,
|
|
|
Цитата _lcf_ @ Так сделать можно, да.ну что-то типа такого: Цитата _lcf_ @ А вот так нет. В D нельзя создать переменную-ссылку. Нужно использовать указатель. И кстати в твоем случае ссылка выступает уже не как алиас а как просто разыменованный указатель.ну если про использование, то дальше что-то типа: Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#58
,
|
|
|
хм, ну ладно. я думал, вдруг вот это:
![]() ![]() return class_empty; //TODO mmm, not good idea?! можно заменить каким-нибудь ![]() ![]() return null[ptr|opt|magic]; ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#59
,
|
|
|
Цитата applegame @ Но область применения ссылок полностью перекрывается указателями. То бишь без ссылок обойтись можно, а вот без указателей уже нет. Да ну? ![]() ![]() ![]() std::string HelloWorld() { std::string hw = "Hello World!"; return hw; } auto TakingPtr(std::string* str) { return *str; } auto TakingRef(const std::string& str) { return str; } int main() { std::string* hw0 = &HelloWorld(); const std::string& hw = HelloWorld(); auto hw1 = TakingPtr(&std::string("Hello World!")); auto hw2 = TakingRef(std::string("Hello World!")); std::cout << *hw0 << std::endl; std::cout << hw << std::endl; std::cout << hw1 << std::endl; std::cout << hw2 << std::endl; } Без привлечения компилятора скажи - что будет выведено на экран? А потом возьми компилятор и проверь. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#60
,
|
|
|
Цитата _lcf_ @ А что мешает просто вернуть указатель на класс? А в качестве пустого значения null? Зачем эта странная движуха со ссылками?можно заменить каким-нибудь Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#61
,
|
|
|
После этого попробуй замутить move-семантику без привлечения rv-ссылок.
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#62
,
|
|
|
Я конечно подзабыл плюсы, но разве вот это не кака?
Цитата std::string* hw0 = &HelloWorld(); const std::string& hw = HelloWorld(); Ты же пытаешься получить указатель и ссылку на временный объект, возвращенный из функции? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#63
,
|
|
|
Цитата applegame @ Ты же пытаешься получить указатель и ссылку на временный объект, возвращенный из функции? Да. Но тут есть нюанс, завязанный на то, что ссылки - это не указатели. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#64
,
|
|
|
Цитата Flex Ferrum @ Я не знаю, что будет выведено на экран, так как у тебя тут сплошной UB. Подозреваю, что если повезет, то выведет четыре раза "Hello World!". Ну или крашнется. Можно запускать компилятор? Да. Но тут есть нюанс, завязанный на то, что ссылки - это не указатели. Добавлено насколько я понял только в этой строке все норм: ![]() ![]() auto hw2 = TakingRef(std::string("Hello World!")); потому что будет создана копия с временного объекта переданного в TakingRef по константной ссылке, и эта копия будет сохранена в hw2; Добавлено Цитата Flex Ferrum @ Дык жили же столько лет без rv-ссылок. После этого попробуй замутить move-семантику без привлечения rv-ссылок. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#65
,
|
|
|
Система типов, видимо, интересна только мне. Хнык-хнык.
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#66
,
|
|
|
Цитата applegame @ Зачем эта странная движуха со ссылками? блин, наверное, невнятно выразился, поправляю: Цитата _lcf_ @ ну если про использование, то дальше что-то типа: ![]() ![]() for (auto t : enum_range (some_class_enum_mode::COUNT)) { some_class *&sc = get_class_for_mode (some_class_enum_mode(t)); if (sc) { sc = new some_class; } } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#67
,
|
|
|
Цитата applegame @ Ты же пытаешься получить указатель и ссылку на временный объект, возвращенный из функции? Константная ссылка продлевает жизнь объекта до времени жизни самой ссылки. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#68
,
|
|
|
да, как альтернатива той портянке, что я привел - передача указателя на указатель в параметрах функции. да вот беда, если для some_class есть шаблонный врапер с чейнами...
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#69
,
|
|
Цитата Flex Ferrum @ Но тут есть нюанс, завязанный на то, что ссылки - это не указатели. А зачем вообще этот нюанс ввели? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#70
,
|
|
|
Цитата applegame @ Я не знаю, что будет выведено на экран, так как у тебя тут сплошной UB. Подозреваю, что если повезет, то выведет четыре раза "Hello World!". В этом коде нет UB. Но есть две ошибки компиляции, вызванные тем, что нельзя брать адрес временного объекта - ни при возврате значения из функции, ни при передаче значения в функцию. А вот константные ссылки брать можно. И такой пример - не единственный. Как правильно было замечено выше, константная ссылка на возвращённый объект продлевает его время жизни до выхода из скоупа. То есть интерпретируется компилятором не как указатель, а как объект целиком. Весело, правда? ![]() ![]() Цитата applegame @ Дык жили же столько лет без rv-ссылок. Угу. Жили, кололись, плакали и кушали кактус. Хорошо жили. Ага. ![]() Добавлено Цитата OpenGL @ А зачем вообще этот нюанс ввели? А вот кабы я знал. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#71
,
|
|
|
Цитата Flex Ferrum @ Но так то конечно - можно продолжать думать, что ссылки - это те же указатели, вид в профиль. ![]() А то, что это костыль в системе типов можно думать? ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#72
,
|
|
|
Цитата D_KEY @ А то, что это костыль в системе типов можно думать? Тебе в который раз повторить, что ссылка типом не является? ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#73
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ А то, что это костыль в системе типов можно думать? Тебе в который раз повторить, что ссылка типом не является? ![]() Ты лучше пруф приведи ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#74
,
|
|
|
Цитата Flex Ferrum @ Тебе в который раз повторить, что ссылка типом не является? ![]() Цитата D_KEY @ Ты лучше пруф приведи ![]() Как я понимаю - ссылка является частью типа данных, но не каким то конкретным типом. Вот например, из того же Маерса, самое начало: Цитата Простейшая ситуация - когда ParamType является ссылочным типом или типом указателя, но не универсальной ссылкой. В этом случае вывод типа работает следующим образом. 1. Если типом expr является ссылка, ссылочная часть игнорируется. 2. Затем выполняется сопоставление типа expr с ParamType для определения T. Например, если у нас имеются шаблон ![]() ![]() template<typename Т> void f( T& param) ; // param представляет собой ссыпку и объявления переменных ![]() ![]() int х = 27 ; // х имеет тип int const int сх = х; // сх имеет тип const int const int& rx = х; // rx является ссыпкой на х как на const int то выводимые типы для pa ram и Тв разл ичных выводах будут следующ ими: ![]() ![]() f (х) ; // Т - int , тип param - int& f( cx) ; // Т - const int , тип param - coпst int& f( rx) ; // Т - const int , тип param - const int& Вот из стандарта: Цитата 11.3.2 References [dcl.ref] 1 In a declaration T D where D has either of the forms & attribute-specifier-seqopt D1 && attribute-specifier-seqopt D1 and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is “derived-declarator-type-list reference to T”. The optional attribute-specifier-seq appertains to the reference type. Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name (10.1.3, 17.1) or decltype-specifier (10.1.7.2), in which case the cv-qualifiers are ignored. [ Example: typedef int& A; const A aref = 3; // ill-formed; lvalue reference to non-const initialized with rvalue The type of aref is “lvalue reference to int”, not “lvalue reference to const int”. — end example ] [ Note: A reference can be thought of as a name of an object. —end note ] A declarator that specifies the type “reference to cv void” is ill-formed. 2 A reference type that is declared using & is called an lvalue reference , and a reference type that is declared using && is called an rvalue reference. Lvalue references and rvalue references are distinct types. Except where explicitly noted, they are semantically equivalent and commonly referred to as references. 3 [ Example: Ссылка - это скорее атрибут типа, чем тип. Нет ссылочного типа данных в С++. Есть указатели, ссылки - это атрибут типа. Добавлено А как там уже их компилятор оптимизирует - это его личное дело, хоть пусть новый указатель заводит. Это конкретная реализация компилятора. Главное что бы поведение этих ссылок отвечало требованию стандарта. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#75
,
|
|
|
Цитата KILLER @ the type of the identifier of D is “derived-declarator-type-list reference to T”. ... The type of aref is “lvalue reference to int”, ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#76
,
|
|
|
Цитата D_KEY @ ![]() Можно по подробнее? Ну подробнее чем просто смайлик? С чем ты не согласен? Если хочешь - можешь перевести что там написано, а то я в английском вообще не понимаю, полный ноль. Спасибо. Добавлено К слову, не знаю как там D, в C# ровно такая же фиговина, этот D очень сильно на C# похож, там тоже ссылочная семантика, но ЕМНИП - структуры, передаются по значению, и есть даже модификаторы типа out, ref которые явно можно указывать в параметрах методов. Так вот ref - ведет себя как ссылка, а out - как указатель. Вся фишка в том, что об этом все знают, им нет дела до того - как это работает в плюсах, там просто свои правила и все. Они не применимы к С++. Так же как и на оборот. Просто ваш спор напоминает спор слепого с глухим )) Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#77
,
|
|
|
Цитата KILLER @ и есть даже модификаторы типа out, ref которые явно можно указывать в параметрах методов. Так вот ref - ведет себя как ссылка, а out - как указатель. Это не модификатора типа ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#78
,
|
|
|
Цитата D_KEY @ И мой вопрос относительно C++ как раз о том, нахрена там ссылка является частью типа? Какую пользу это несёт? По-моему это только усложняет систему типов, добавляет кучу правил и исключений из них. Где там? Цитата D_KEY @ Какую пользу это несёт? В основном - быстродействие. Это несет очень большую пользу. В основном ты работаешь просто с другими задачами на этих языках. И там в основном нужен динамический полиморфизм. Смысла в основном нет использовать какие то примитивные типы, ты просто получил коробку с кучей возможностей, не задумываясь о том, как это выглядит на более низком уровне. Добавлено Цитата D_KEY @ По-моему это только усложняет систему типов, добавляет кучу правил и исключений из них. Вот тебе С++ ![]() ![]() void f (Widget&& param) ; // rvalue - ccылкa Widget&& var1 = Widget () ; // rvalue- ccылкa auto&& var2 = var1 ; // Не rvalue- ccылкa (универсалоьная ссылка) template<typename Т> void f( std::vector<T>&& param) ; // rvalue- ccылкa template<typename T> void f(T&& param); // Не rvalue - ccылкa (универсалоьная ссылка) Усложняет или нет? Ты понял идею того, что описано выше? В C# нет такой проблемы в принципе например. Но там есть ref и out. А еще там ссылочная семантика. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#79
,
|
|
|
KILLER, зачем ты все это написал?
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#80
,
|
|
|
Цитата D_KEY @ Ты понимаешь, что ссылки можно было добавить в язык не добавляя их в систему типов и не делая их частью типов? Мой вопрос об этом. Тогда было бы очень громоздко писать программы. Ты рехнулся? Везде писать вместо & - ref? Нет уж, увольте, пусть будет так как есть. Ты видимо не до конца понимаешь концепцию ссылочной семантики и ссылок в С++ или что? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#81
,
|
|
|
Цитата D_KEY @ И мой вопрос относительно C++ как раз о том, нахрена там ссылка является частью типа? Какую пользу это несёт? Эта "часть типа" показывает компилятору что можно, а что нельзя делать с конкретно этим вариантом типа. Как было продемонстрировано в примерах выше. И это относится не только к передаче аргументов в функцию. Добавлено Цитата D_KEY @ Ты понимаешь, что ссылки можно было добавить в язык не добавляя их в систему типов и не делая их частью типов? Нельзя. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#82
,
|
|
|
Представь есть у тебя тип данных - Любой. Так вот - ты можешь сделать на него указатель, и у тебя получится совершенно другой тип данных, будет Любой*, а ссылка - это просто некий атрибут, с помощью которого, ты говоришь - вот тут я не хочу копировать весь объект, хочу чтоб он вошел внутрь как есть, а вот тут - я буду вообще управлять им с помощью другого идентификатора. Это не тип - это атрибут, или как то так, типа. Это не является типом данных, это всего лишь реально атрибут. Как то так.
Цитата D_KEY @ KILLER, зачем ты все это написал? Это, ты веки подними выше кода )) Там написано зачем я это писал. Я же говорю - вы спорите о двух разных вещах, и так главное все повелись. Вот в С# похоже что ровно тоже самое что и в D, но тем не менее - те недостатки, которые ты описываешь - они там не возникают вообще никак. Я не знаю, может просто я с таким не сталкивался. Возможно, но реально это из области фантастики. Вы спорите о разном просто. Вот и все )) Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#83
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ Ты понимаешь, что ссылки можно было добавить в язык не добавляя их в систему типов и не делая их частью типов? Нельзя. Почему? Добавлено KILLER, это часть типа в C++. Перечитай свои же цитаты из стандарта и авторитетного для тебя автора. Добавлено Flex Ferrum, в D&E Страуструп пишет, что столкнулся с проблемой добавления перегрузки операторов в язык и для ее устранения ввел ссылки. Если бы вместо добавления ссылок в систему типов он бы добавил ключевые слова(ну или тот же &) для указания способа передачи аргумента в функцию(ну и для возврата), то его проблема была бы решена. Какие негативные последствия такого решения ты видишь? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#84
,
|
|
|
Цитата D_KEY @ KILLER, это часть типа в C++. Это часть типа в С++? Ок, тогда ты согласен что это не тип данных, о чем тебе Флекс и говорил? Или как? Цитата D_KEY @ Перечитай свои же цитаты из стандарта и авторитетного для тебя автора. Там уже по 5 раз все прочитано, по крайней мере Маерса. Что там написано в стандарте - ты выдрал 5 слов от туда, и поставил смайлик, и чего мне делать на этот весомый аргумент? Я же просил - переведи мне на русский что там написано, я не понимаю же )) Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#85
,
|
|
|
Цитата KILLER @ Это часть типа в С++? Ок, тогда ты согласен что это не тип данных, о чем тебе Флекс и говорил? О чем там говорил Flex я не понял. Он говорил, что ссылка является модификатором типа, но пруфы из стандарта приводить не стал. В стандарте же постоянно ссылки считаются типом во многих местах. Раздел про ссылки ты видел, в разделе о типах так же говорится, что типы описывают и ссылки в том числе. Ссылки в качестве типа встречаются много где... Тип данных? Что ты под этим подразумеваешь? Типы в C++ описывают объекты, функции и ссылки. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#86
,
|
|
Цитата applegame @ Значит-таки нет.Да. Потому что упомянутый тобой pointer aliasing в плюсах относится не только к указателям, но и к ссылкам. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#87
,
|
|
|
Цитата Flex Ferrum @ Я скомпилировал в гцц с ключом и запустил. Вывело четыре раза хелловорлд. В этом коде нет UB. Но есть две ошибки компиляции, вызванные тем, что нельзя брать адрес временного объекта - ни при возврате значения из функции, ни при передаче значения в функцию. ![]() Цитата Flex Ferrum @ Нет. Ссылка будет интерпретироваться как указатель на временный объект в стеке. То есть интерпретируется компилятором не как указатель, а как объект целиком. Добавлено Цитата Qraizer @ Очень аргументированно. Могу привести пример этого самого pointer aliasinga с ссылками, если хочешь. Значит-таки нет. Добавлено Цитата Flex Ferrum @ Так предлагается убрать ссылочный тип. Тогда и компилятору не нужно ничего знать о том, что можно, а чего нельзя делать с несуществующим типом.Эта "часть типа" показывает компилятору что можно, а что нельзя делать с конкретно этим вариантом типа. Как было продемонстрировано в примерах выше. И это относится не только к передаче аргументов в функцию. Цитата Flex Ferrum @ Можно. Нельзя. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#88
,
|
|
Цитата applegame @ А ты ещё раз перечитай. Альясинг там приведёт как самый простой и распространённый пример запрета компилятору на агрессивную оптимизацию. Естественно этот пример не единственный, пост начинался-то с общего тезиса. В завершении же поста указано, как ссылки могут помочь восстановить разрешение на агрессивную оптимизацию там, где указатели пасуют. Очень аргументированно. Могу привести пример этого самого pointer aliasinga с ссылками, если хочешь. Добавлено Цитата applegame @ Ухудшит. Указывать на недавние посты в этой теме не буду. Просто возьми и перестань пользоваться ссылками, сам поймёшь, если аргументы не доходят.Что мы потеряем, если внезапно исчезнет ссылочный тип? ... Ну так это же прекрасно, это только улучшит язык. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#89
,
|
|
Цитата Qraizer @ Ухудшит. "Улучшит" относилось к исчезновению наличия странной возможности давать ссылки на временные объекты, продлевая их жизнь. Цитата Qraizer @ Просто возьми и перестань пользоваться ссылками, сам поймёшь, если аргументы не доходят. Легко, если появится компилятор С++ с изменениями, которые тут описывались. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#90
,
|
|
|
Цитата Qraizer @ Перечитал еще раз. Я тебя прекрасно понял и у меня создалось впечатление, что ты немного не понимаешь, что такое pointer aliasing.А ты ещё раз перечитай. Ссылки не помогут компилятору избежать косяков с pointer aliasing. Потому что эта проблема вообще ортогональна способу реализации алиасов. И ссылки и указатели - это суть алиасы на некую область памяти. С разной семантикой, но и то и другое - алиасы. Вот ты пишешь: Цитата Qraizer @ С помощью ссылки ты "защищаешь" некое "значение" ссылки (хотя формально "значения" у ссылки нет, но мы сделаем вид, что есть), а проблема-то возникает не со "значением" ссылки, а с объектом на короый она ссылается, а его она защищает не лучше указателя. С тем же успехом ты можешь создать константный указатель, компилятор тоже будет знать, что "единственное место, где т.к. единственное место, где ссылка может поменять своё значение – это точка её инициализации. ![]() ![]() void foo(int& b) { int* const a = &b; // ничем не лучше чем int& a; } ЕМНИП, стандарт регламентирует поведение компилятора таким образом, что если два алиаса указывают на объекты разных типов, то компилятору разрешается считать, что они не могут ссылаться на одну и ту же область памяти. И совершенно пофиг являются ли эти алиасы ссылками или указателями. Если у тебя есть две ссылки разного типа, но указывающие в одно и тоже место - ничего хорошего не жди: ![]() ![]() #include <cstdio> int foo(int& x, long& y) { x = 5; y = 10; return x; } int main() { long y = 1; foo(*(int*)y, y); printf("y = %d", y); // ??? } Цитата Qraizer @ Какие посты? То что привел Флекс? В здравом уме и трезвой памяти такой говнокод никто не пустит в серьезный проект.Ухудшит. Указывать на недавние посты в этой теме не буду. Цитата Qraizer @ Я ими уже пару лет как не пользуюсь, с тех пор как перешел на D, потому что там ссылочный тип отсутствует. Просто возьми и перестань пользоваться ссылками, сам поймёшь, если аргументы не доходят. Добавлено Цитата OpenGL @ Как можно жить без таких архиполезных конструкций как:"Улучшит" относилось к исчезновению наличия странной возможности давать ссылки на временные объекты, продлевая их жизнь. ![]() ![]() const int& a = 10; // WAT??? Добавлено Флексу же предлагаю нашу ветку спора завершить. Думаю мы поняли друг-друга. Во всяком случае я согласен, что программируя на C++ будет правильно считать ссылки некими псевдонимами на объекты, а не особыми разыменованными указателями (даже если для какого-нибудь бэкенда GCC они суть одно и тоже). В таком контексте всякие странности перестают быть странностями. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#91
,
|
|
|
Я бы хотел продолжить разговор о системе типов...
Возможно, я что-то упускаю. Хочу понять. С точки зрения практики я не понимаю, зачем так было усложнять язык. Столько всяких сложных правил из-за ссылок в системе типов(перегрузка, шаблоны и их специализация, вывод типа аргумента шаблона, auto, decltype). На первый взгляд кажется, что это бессмысленное усложнение и ссылки просто как способ передачи/возврата позволяли решить исходные проблемы без такого усложнения. Но я могу ошибаться. С точки зрения теории вообще все грустно, ИМХО. Если рассматривать типы как множество значений + множество операций, то у T& и T совпадают оба множества. Если же мы возьмём какой-нибудь TAPL, где упор делается на классификации выражений, то все становится ещё непонятнее. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#92
,
|
|
|
Цитата D_KEY @ Без ссылочного типа можно легко обойтись, но его наличие не мешает:С точки зрения практики я не понимаю, зачем так было усложнять язык. Столько всяких сложных правил из-за ссылок в системе типов(перегрузка, шаблоны и их специализация, вывод типа аргумента шаблона, auto, decltype). На первый взгляд кажется, что это бессмысленное усложнение и ссылки просто как способ передачи/возврата позволяли решить исходные проблемы без такого усложнения. Но я могу ошибаться. ![]() ![]() void foo(S& s) { auto& f = S.field; // auto* const f = S.field; int c = f.a1 + f.a2 + f.a3; // int c = f->a1 + f->a2 + f->a3; } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#93
,
|
|
|
Цитата applegame @ Цитата D_KEY @ Без ссылочного типа можно легко обойтись, но его наличие не мешает:С точки зрения практики я не понимаю, зачем так было усложнять язык. Столько всяких сложных правил из-за ссылок в системе типов(перегрузка, шаблоны и их специализация, вывод типа аргумента шаблона, auto, decltype). На первый взгляд кажется, что это бессмысленное усложнение и ссылки просто как способ передачи/возврата позволяли решить исходные проблемы без такого усложнения. Но я могу ошибаться. ![]() ![]() void foo(S& s) { auto& f = S.field; // auto* const f = S.field; int c = f.a1 + f.a2 + f.a3; // int c = f->a1 + f->a2 + f->a3; } Тут так же нет смысла в типе. Можно разрешить объявлять переменные-ссылки. Поведение будет то же. У f будет иметь "обычный" тип. Добавлено Ссылка/значение - это "свойство" переменной, а не типа. Т.к. единственное, что тут затронуто - вопрос об идентификации объекта. При чем тут тип? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#94
,
|
|
|
Возьмём классику жанра:
![]() ![]() cout << "Hello World" << someBigObject << 123 << endl; Представим, что в с++ нет ссылок, но есть ref. Как этот код будет работать и как будет выглядеть оператор вывода в поток? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#95
,
|
|
|
Цитата Flex Ferrum @ Также как и сейчас. Ведь предлагается убрать не ссылки, а ссылочный тип. и как будет выглядеть оператор вывода в поток? Добавлено Цитата D_KEY @ В таком смысле, наверное ты прав.Тут так же нет смысла в типе. Можно разрешить объявлять переменные-ссылки. Поведение будет то же. У f будет иметь "обычный" тип. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#96
,
|
|
|
Цитата applegame @ Цитата Flex Ferrum @ Также как и сейчас. Ведь предлагается убрать не ссылки, а ссылочный тип.и как будет выглядеть оператор вывода в поток? Ты не мудри, ты пальцем покажи. И объясни. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#97
,
|
|
|
Цитата Flex Ferrum @ Возьмём классику жанра: ![]() ![]() cout << "Hello World" << someBigObject << 123 << endl; Представим, что в с++ нет ссылок, но есть ref. Как этот код будет работать и как будет выглядеть оператор вывода в поток? Ну как-то так ![]() ![]() ref std::ostream operator << (ref std::ostream os, const char * str) { ... return os; } ref std::ostream operator << (ref std::ostream os, ref const my_type obj) { ... return os; } ref std::ostream operator << (ref std::ostream os, int x) { ... return os; } Работать будет так же, как и ссылки сейчас. Да, в принципе, можно и синтаксис с & оставить. Я что-то упускаю? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#98
,
|
|
Цитата Flex Ferrum @ Как этот код будет работать и как будет выглядеть оператор вывода в поток? А что ему принципиально будет мешать работать? Мне вот вообще интересно - что в языке сломается, если не будет правила "константная ссылка на временную переменную расширяет область видимости до области видимости ссылки". Точнее, даже два случая можно рассмотреть: 1) Что сломается, если это правило вообще убрать? 2) Что сломается, если расширить его и на неконстатные ссылки? В случае 2) вроде должен компилиться такой код: ![]() ![]() void foo(std::string &s) { s = "42"; } std::string bar() { return "24"; } foo(bar()); что вроде не так уж и плохо. Но скорей всего подобного же можно добиться и другими изменениями. А вот 1 - совершенно непонятно. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#99
,
|
|
|
ОФФТОП.
надыбал забавные грабли в плюсах. Что выведет на экран следующая программа? ![]() ![]() #include <iostream> struct A { A (int i) { std::cout << 'A';} }; struct B { B (A a) { std::cout << 'B';} }; int main () { int i = 1; B b(A(i)); return 0; } Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#100
,
|
|
|
Цитата applegame @ ОФФТОП. надыбал забавные грабли в плюсах. Что выведет на экран следующая программа? ![]() ![]() #include <iostream> struct A { A (int i) { std::cout << 'A';} }; struct B { B (A a) { std::cout << 'B';} }; int main () { int i = 1; B b(A(i)); return 0; } Этим граблям сто лет в обед. ![]() ![]() Добавлено Цитата D_KEY @ Работать будет так же, как и ссылки сейчас. Да, в принципе, можно и синтаксис с & оставить. Что-то я тогда не пойму, в чём профит. Если и работать будет так же, и & можно оставить, то в чем отличие то будет? И *, и & всегда относились к имени переменной, а не к имени типа. Это ж букварь. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#101
,
|
|
|
Цитата Flex Ferrum @ Что-то я тогда не пойму, в чём профит. Не будет такого типа как T &. Не будет такой специализации шаблона, например. Не будет странного типа без размера в языке. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#102
,
|
|
|
Цитата Flex Ferrum @ И *, и & всегда относились к имени переменной, а не к имени типа. Это ж букварь. ![]() С указателем что то я не понял, с чего вдруг к имени переменной? Т.е. указатель это не тип данных? Тогда например взять void - если указатель относится к имени переменной, то почему void* ptr - я могу написать, а void p - не могу написать? И опять же тот же typeid не выкидывает * при выводе типа. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#103
,
|
|
|
Цитата D_KEY @ Цитата Flex Ferrum @ Что-то я тогда не пойму, в чём профит. Не будет такого типа как T &. Не будет такой специализации шаблона, например. Не будет странного типа без размера в языке. А куда ж оно денется то? Вот захочешь ты передать в шаблонный метод параметр, который пришёл как ref, какого типа он будет? Добавлено Цитата KILLER @ Цитата Flex Ferrum @ И *, и & всегда относились к имени переменной, а не к имени типа. Это ж букварь. ![]() С указателем что то я не понял, с чего вдруг к имени переменной? Т.е. указатель это не тип данных? Тогда например взять void - если указатель относится к имени переменной, то почему void* ptr - я могу написать, а void p - не могу написать? И опять же тот же typeid не выкидывает * при выводе типа. Говорю же - это букварь. ![]() int* p, c; То p будет указателем, а c - нет. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#104
,
|
|
|
Сообщ.
#105
,
|
|
|
Цитата Flex Ferrum @ А куда ж оно денется то? Вот захочешь ты передать в шаблонный метод параметр, который пришёл как ref, какого типа он будет? Параметр, который пришел как ref T будет иметь тип T, соответственно и в шаблонный метод он придет как T. ![]() ![]() template<T> void foo(T t) {} template<T> void foo(ref T t) {} void bar(ref int a) { foo(a); fooRef(a); } Добавлено Цитата Flex Ferrum @ Но забавляют до сих пор. Этим граблям сто лет в обед. ![]() ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#106
,
|
|
Цитата applegame @ Тьфу. Всё, сотри pointer aliasing из своей памяти. Нет примера. Сам придумай.Я тебя прекрасно понял и у меня создалось впечатление, что ты немного не понимаешь, что такое pointer aliasing. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#107
,
|
|
Цитата applegame @ В школу. На урок информатики, 8-го класса. Прости, цензурные эпитеты кончились. С помощью ссылки ты "защищаешь" некое "значение" ссылки (хотя формально "значения" у ссылки нет, но мы сделаем вид, что есть), а проблема-то возникает не со "значением" ссылки, а с объектом на короый она ссылается, а его она защищает не лучше указателя. Добавлено Цитата applegame @ Нет. И это тоже надо объяснять?? Пожалуй, я пойду отсюда. У Flex Ferrum-а нервы крепче.С тем же успехом ты можешь создать константный указатель, компилятор тоже будет знать, что "единственное место, где Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#108
,
|
|
|
Qraizer, мда...
Добавлено Qraizer, по типам скажешь что-нибудь или тоже нет? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#109
,
|
|
Вот это, пожалуй, единственное серьёзное замечание.
Цитата applegame @ Видишь ли, библиотекам обычно плевать, что там написано у нас, а нам зачастую плевать, как реализованы библиотеки. И если каждое из обоих написаны безупречно, то это ещё не означает, что собранные в одну кучу они окажутся счастливы. В здравом уме и трезвой памяти такой говнокод никто не пустит в серьезный проект. Добавлено Цитата D_KEY @ А чего ты ожидал? Просто интересно. Я вот к примеру, не ожидал, что пишу для Исмаила Прокопенко. Qraizer, мда... Добавлено P.S. По системе типов я сказал. Не тебе, правда, но applegame-у тоже не понравилось. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#110
,
|
|
|
Цитата Qraizer @ P.S. По системе типов я сказал. Не тебе, правда, но applegame-у тоже не понравилось. Если не сложно, тыкни где. Плохо следил за вашим обсуждением. Но если что, сам потом поищу. Добавлено Цитата Qraizer @ А чего ты ожидал? Аргументации. И объяснения, если человек не понимает. Ты умеешь, я помню. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#111
,
|
|
Шо, опять "вы дураки, я умный"? Печально
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#112
,
|
|
|
Цитата Qraizer @ В школу. На урок информатики, 8-го класса. Прости, цензурные эпитеты кончились. Цитата Qraizer @ Qraizer, такой Qraizer. Нет. И это тоже надо объяснять?? Пожалуй, я пойду отсюда. У Flex Ferrum-а нервы крепче. ![]() Цитата D_KEY @ Человек все прекрасно понимает. А вот оппоненту нечего возразить и все сводится как обычно кАргументации. И объяснения, если человек не понимает. Ты умеешь, я помню. Цитата OpenGL @ "вы дураки, я умный" ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#113
,
|
|
Цитата D_KEY @ Четвёртый раз одно и то же? Ещё прошлым летом надоело. Аргументации. Добавлено А хотя давай. Добавлено Цитата applegame @ В общем случае не может. Даже больше: может в ограниченном количестве случаев. Всё потому, что указатель доступен программисту как есть, поэтому компилятор не может гарантировать, кто где-то, в невидимом ему контексте, этот указатель программером не поменяется, даже если всё время жизни объекта-указателя у него перед глазами. ... Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Которые доступны при замене указателей на ссылки, т.к. единственное место, где ссылка может поменять своё значение – это точка её инициализации. Конечно, невелика разница, если рассматриваемый объект является параметром функции/метода, но достаточно представить себе поле класса, и тут уже не всё так шоколадно с указателями и всё прекрасно с ссылками.Компилятор запросто может и разыменованный указатель соптимизировать и не создавать реальной переменной. А может и ссылку создать в виде указателя, если ему приспичит. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#114
,
|
|
|
Цитата applegame @ Какие посты? То что привел Флекс? В здравом уме и трезвой памяти такой говнокод никто не пустит в серьезный проект. Да. Вот тут стоит прокомментировать. Это ни разу не говнокод. Ситуаций в реальном коде, когда temporary object биндится к l-value (или r-value) reference - пруд пруди. Собственно, это любой вызов, где происходит неявный каст через инициализирующий конструктор. Или где в одну функцию передаётся результат работы другой. И т. п. Вот когда возвращаемое значение надо биндить к явной ссылке на константу - сходу сказать не могу. Очевидно, что константные указатели в этой ситуации не помогут от слова "совсем". Ибо указатель - это указатель. То, с чем можно работать явно (в отличие от ссылки). И (ещё раз) это отличие - принципиальное. Добавлено Цитата Qraizer @ Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Что и было мною продемонстрировано на примерах. Но это, почему-то, не аргумент. ![]() ![]() Добавлено Цитата Qraizer @ но достаточно представить себе поле класса, и тут уже не всё так шоколадно с указателями и всё прекрасно с ссылками. Поясни примером кода, что ты имеешь в виду. Добавлено Цитата D_KEY @ Flex Ferrum, можешь кодом? Цитата applegame @ Параметр, который пришел как ref T будет иметь тип T, соответственно и в шаблонный метод он придет как T. Ну да. Тут applegame правильно сказал. Это я запамятовал. Цитата D_KEY @ Не будет такого типа как T &. Не будет такой специализации шаблона, например. Не будет странного типа без размера в языке. BTW, в плюсах от этого всё равно никуда не деться. Вот, скажем, код: ![]() ![]() #include <iostream> #include <string> using namespace std; template<typename Os, typename Cont, typename Delim> void PrintContainer(Os&& os, Cont&& cont, Delim delim) { bool isFirst = true; for (auto& v : cont) { if (!isFirst) os << delim; else isFirst = false; os << v; } } int main() { auto& os = std::cout; std::string hw = "Hello World!"; PrintContainer(std::cout, hw, ", "); return 0; } Он прекрасно работает с любыми комбинациями передаваемых значений. И, опять же, хороший пример того, что ссылочный тип - это больше инструкции компилятору и относится к декларации параметра, а не типа. В зависимости от того, что передаётся в PrintContainer шаблонные типы могут оказаться как правыми сслыками, так и левыми на константы, так и конкретными значениями. Кто-то называет такой приём universal reference, но на самом деле тут работают правила "схлопывания" ссылок. Добавлено Цитата applegame @ Если у тебя есть две ссылки разного типа, но указывающие в одно и тоже место - ничего хорошего не жди: Как это. Можно и зайца научить курить. Нет ничего невозможного для человека с интеллектом. Но только вот зачем? Да, действительно, в С++ можно обойти встроенные в компилятор механизмы защиты и контроля корректности. Только вот зачем это делать без крайней на то необходимости? Как раз таки приведённые игрища с ссылками и есть говнокод. Добавлено Но хотя бы лишь то отличие, что ссылку нельзя оставить неинициализированной - уже огромный плюс. Ибо сейчас (в очередной раз) напоролся на то, что профачил инициализацию указателя, а потом к нему обратился. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#115
,
|
|
|
Цитата Qraizer @ Лучше не надо. Все равно твоя аргументация сводится к отсылкам к собственным постам (в том числе в весьма отдаленном прошлом), к фейспалмами и советам пойти куда-нибудь далеко учить матчасть. Такую "аргументацию" оставь при себе.А хотя давай. Цитата Flex Ferrum @ Да, это встречается очень часто. Но речь-то шла не об этом, а о:Ситуаций в реальном коде, когда temporary object биндится к l-value (или r-value) reference - пруд пруди. Собственно, это любой вызов, где происходит неявный каст через инициализирующий конструктор. Или где в одну функцию передаётся результат работы другой. И т. п. Цитата Flex Ferrum @ Вот это я назвал говнокодом.Вот когда возвращаемое значение надо биндить к явной ссылке на константу - сходу сказать не могу. Цитата Flex Ferrum @ А причем тут константные указатели? Твой пример обсуждался в контексте ценности подобных "умений" ссылок, а не сравнения с константными указателями. Константные указатели появились в споре с Qraizerом, не с тобой.Очевидно, что константные указатели в этой ситуации не помогут от слова "совсем". Ибо указатель - это указатель. То, с чем можно работать явно (в отличие от ссылки). И (ещё раз) это отличие - принципиальное. Цитата Flex Ferrum @ Забавно, что ты не заметил, что продемонстрировал строго обратное Цитата Qraizer @ Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Что и было мною продемонстрировано на примерах. Но это, почему-то, не аргумент. ![]() Qraizer, говорил, о том, что, в отличие от указателей, ссылки помогают избежать опасных агрессивных оптимизаций. А ты привел пример, где, наоборот, ссылка агрессивно соптимизировалась. Кроме того, никакого pointer aliasing в твоей демонстрации нет. Вы братцы, похоже, совсем запутались в дебрях реализаций. Передозировка абстракциями налицо. ![]() Цитата Flex Ferrum @ Ну я тоже так умею. Оказывается, я повёл себя нечестно, запретив оптимизировать указатель. ![]() ![]() ![]() Цитата Flex Ferrum @ Ну этот код не противоречит концепции отсутствия ссылочного типа. Представь, что если ты будешь определять тип переменных os и cont в теле функции PrintContainer, то компилятор будет говорить, что их тип std::cout и std::string соответственно, а не std::cout&& и std::string&&. Правда возникает резонный вопрос, а что тогда меняет такое вот упразднение ссылочного типа?BTW, в плюсах от этого всё равно никуда не деться. Вот, скажем, код: ![]() ![]() #include <iostream> #include <string> using namespace std; template<typename Os, typename Cont, typename Delim> void PrintContainer(Os&& os, Cont&& cont, Delim delim) { bool isFirst = true; for (auto& v : cont) { if (!isFirst) os << delim; else isFirst = false; os << v; } } int main() { auto& os = std::cout; std::string hw = "Hello World!"; PrintContainer(std::cout, hw, ", "); return 0; } Он прекрасно работает с любыми комбинациями передаваемых значений. И, опять же, хороший пример того, что ссылочный тип - это больше инструкции компилятору и относится к декларации параметра, а не типа. В зависимости от того, что передаётся в PrintContainer шаблонные типы могут оказаться как правыми сслыками, так и левыми на константы, так и конкретными значениями. Кто-то называет такой приём universal reference, но на самом деле тут работают правила "схлопывания" ссылок. Цитата Flex Ferrum @ Абсолютно согласен. Pointer aliasing из этой самой серии. И это Qraizer завел об этом разговор, не я. Типа ссылки помогут избежать глюков компилятора в таком вот говнокоде. Во-первых, не помогут, во-вторых, как ты справедливо заметил, можно и зайца научить курить.Цитата applegame @ Если у тебя есть две ссылки разного типа, но указывающие в одно и тоже место - ничего хорошего не жди: Как это. Можно и зайца научить курить. Нет ничего невозможного для человека с интеллектом. Но только вот зачем? Да, действительно, в С++ можно обойти встроенные в компилятор механизмы защиты и контроля корректности. Только вот зачем это делать без крайней на то необходимости? Как раз таки приведённые игрища с ссылками и есть говнокод. Цитата Flex Ferrum @ Ну это, конечно, плюс, но не перед указателями. Тут бы тебе помог тот самый константый указатель. Тогда компилятор не дал бы тебе профачить его инициализацию. Но хотя бы лишь то отличие, что ссылку нельзя оставить неинициализированной - уже огромный плюс. Ибо сейчас (в очередной раз) напоролся на то, что профачил инициализацию указателя, а потом к нему обратился. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#116
,
|
|
|
Оппа, вот это поворот!
![]() Похоже на то, что вы, товарищи, включая нашего уважаемого гуру Флекса (и меня конечно, но мне простительно ![]() Так вот, если из функции возвращается ссылка на временный объект, то его нельзя биндить к константной ссылке. И пофиг был ли этот временный объект создан внутри функции или в выражении вызова функции и передан в качестве параметра: Цитата cppreference.com - reference initialization Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions: - a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference. ... - a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference. Вот тут, Флекс смухлевал (полагаю, что не намеренно, а токмо по ошибке): Цитата Flex Ferrum @ Данная функция вернет отнюдь не ссылку, а значение - копию параметра - https://ideone.com/CkeMhZ, которое прибиндится к константной ссылке и все будет ок.![]() ![]() auto TakingRef(const std::string& str) { return str; } А вот если написать: ![]() ![]() auto& TakingRef(const std::string& str) { return str; } Если я неправ - покажите где. Если Флекс ошибся - ждем-с признания ошибки. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#117
,
|
|
|
Цитата applegame @ Вот это я назвал говнокодом. И это не говнокод. Представь, что такой биндинг делается в шаблонном методе, который не знает, что возвращает аргумент-функтор - ссылку или значение. Цитата applegame @ А причем тут константные указатели? Твой пример обсуждался в контексте ценности подобных "умений" ссылок, а не сравнения с константными указателями. Константные указатели появились в споре с Qraizerом, не с тобой. Ну а что, я не могу ответить (или использовать) твои аргументы из спора с Крайзером? Указатель (константный или нет) остаётся указателем, самостоятельным объектом, сущностью. В отличие от ссылки. Цитата applegame @ Забавно, что ты не заметил, что продемонстрировал строго обратное ![]() Я продемонстрировал именно то, что хотел. Компилятор агрессивно оптимизирует ссылки и никто не может ему этого запретить. В отличие от указателей. А там, где разработчик делает компилятору подножки - он сам себе злобный чебуран. Цитата applegame @ Ты мой следующий пример смотрел? Там ссылка тоже перестала оптимизироваться. ![]() Это который? Цитата applegame @ Правда возникает резонный вопрос, а что тогда меняет такое вот упразднение ссылочного типа? А ты возьми и упраздни. Убери && из объявления параметров и посмотри, что получится. Я уже говорил: пример показывает, что ссылка - это не часть типа "вообще", а часть типа конкретного параметра, часть объявления параметра. Цитата applegame @ Pointer aliasing из этой самой серии Pointer Aliasing совсем из другой серии. А относительно говнокода - garbage in, garbage out. Чего удивляться тому, что механизм перестаёт работать, если по нему молотком херачат? Цитата applegame @ Тут бы тебе помог тот самый константый указатель. Тогда компилятор не дал бы тебе профачить его инициализацию. ![]() Не помог бы. У меня этот указатель дальше по коду меняется. Добавлено Цитата applegame @ Оппа, вот это поворот! ![]() Похоже на то, что вы, товарищи, включая нашего уважаемого гуру Флекса (и меня конечно, но мне простительно ![]() Так вот, если из функции возвращается ссылка на временный объект, то его нельзя биндить к константной ссылке. И пофиг был ли этот временный объект создан внутри функции или в выражении вызова функции и передан в качестве параметра: Цитата cppreference.com - reference initialization Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions: - a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference. ... - a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference. Вот тут, Флекс смухлевал (полагаю, что не намеренно, а токмо по ошибке): Цитата Flex Ferrum @ Данная функция вернет отнюдь не ссылку, а значение - копию параметра - https://ideone.com/CkeMhZ, которое прибиндится к константной ссылке и все будет ок.![]() ![]() auto TakingRef(const std::string& str) { return str; } А вот если написать: ![]() ![]() auto& TakingRef(const std::string& str) { return str; } Если я неправ - покажите где. Если Флекс ошибся - ждем-с признания ошибки. Не. Я не ошибся. Я знал, что будет возвращено значение (временный объект). А твой пример - компилятор не может запретить тебе так делать (более того, у него есть подобные функции - std::ref, std::move, std::forward), так что ошибка в этом примере - на совести разработчика. Добавлено Тут только статический анализатор поможет. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#118
,
|
|
|
Цитата Flex Ferrum @ В данном случае не можешь, потому что контекст разный и споры разные.Ну а что, я не могу ответить (или использовать) твои аргументы из спора с Крайзером? Указатель (константный или нет) остаётся указателем, самостоятельным объектом, сущностью. В отличие от ссылки. Цитата Flex Ferrum @ Не выкручивайся. Ты же сказал, что продемонстрировал то о чем говорит Qraizer, а оказалось наоборот. Я продемонстрировал именно то, что хотел. ![]() Цитата Flex Ferrum @ Ага, и ты именно так и сделал. А там, где разработчик делает компилятору подножки - он сам себе злобный чебуран. ![]() Цитата Flex Ferrum @ Вот этот - https://godbolt.org/g/sNgSPXЭто который? Цитата Flex Ferrum @ Нет-нет. Дикей не предлагает убрать && из объявлений. Он предлагает чтобы компилятор перестал это считать типом, а считал этот атрибутами параметров функции или возвращаемого значения. Или он и так не считает? если я обявлю две переменные int& и int, будет ли компилятор считать, что их типы разные?А ты возьми и упраздни. Убери && из объявления параметров и посмотри, что получится. Цитата Flex Ferrum @ Что правда? Ну давай расскажи, как можно схлопотать проблемы с pointer aliasing не говнокодя и как ссыоки помогут бороться с этими проблемами. Ну хоть один примерчик-то можете привести или только утверждения делать мастера?Pointer Aliasing совсем из другой серии. Цитата Flex Ferrum @ Ну а зачем ты тогда ссылки-то вспомнил? Тебе тут и ссылка не поможет.Не помог бы. У меня этот указатель дальше по коду меняется. Цитата Flex Ferrum @ То есть ты намеренно смухлевал? Расскажи еще, что ты знал, что ссылки на временные объекты возвращаемые из функций нельзя биндить даже к константным ссылкам. Я тут тебе цитат понакидаю. Никто тебе не поверит. Не. Я не ошибся. Я знал, что будет возвращено значение (временный объект). ![]() Однако Флексу, оказывается, не чуждо верчение ужом на сковородке. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#119
,
|
|
|
Цитата Flex Ferrum @ Я уже говорил: пример показывает, что ссылка - это не часть типа "вообще", а часть типа конкретного параметра, часть объявления параметра. Достигается это за счёт кучи правил и исключений из них. T& является типом в C++, но с кучей всяких исключений и дополнительных правил. Что в итоге приводит к тому, что он часто ведёт себя не как тип ![]() Вот я и думаю, а что бы было, если бы в язык вместо непонятного типа ввели доп. возможность указывать способ передачи/возврата в/из функции(да и фиг с ним, пусть и локальные синонимы разрешили делать), без изменения системы типов. Правила довольно простые. Система типов не "обогащается" такими странными "полутипами". Пользователи языка не мучаются, даже если начинающие. Вопросы о связи указателей и ссылок вряд ли бы возникали так часто, как сейчас. Разработчикам компиляторов так же было бы намного легче. Добавлено Но у меня смутное чувство, что я что-то упускаю. И возможно это не ошибка дизайна языка, а какой-то гениальный ход, который до меня не доходит. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#120
,
|
|
|
Прошу уполномоченных лиц, отделить обсуждение ссылок в плюсах в отдельную тему. Тут уже давно не пахнет "D vs C++".
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#121
,
|
|
|
Цитата D_KEY @ Цитата Flex Ferrum @ Я уже говорил: пример показывает, что ссылка - это не часть типа "вообще", а часть типа конкретного параметра, часть объявления параметра. Достигается это за счёт кучи правил и исключений из них. T& является типом в C++, но с кучей всяких исключений и дополнительных правил. Что в итоге приводит к тому, что он часто ведёт себя не как тип ![]() Вот я и думаю, а что бы было, если бы в язык вместо непонятного типа ввели доп. возможность указывать способ передачи/возврата в/из функции(да и фиг с ним, пусть и локальные синонимы разрешили делать), без изменения системы типов. Правила довольно простые. Система типов не "обогащается" такими странными "полутипами". Пользователи языка не мучаются, даже если начинающие. Вопросы о связи указателей и ссылок вряд ли бы возникали так часто, как сейчас. Разработчикам компиляторов так же было бы намного легче. Добавлено Но у меня смутное чувство, что я что-то упускаю. И возможно это не ошибка дизайна языка, а какой-то гениальный ход, который до меня не доходит. Я думаю, что если ты попробуешь описать поведение этой замены ссылкам - ты получишь ровно те же яйца, только с видом в профиль. Для верности можешь заглянуть в спецификацию ссылок в стандарте и выкинуть то, что считаешь "лишним" для нового, правильного ref. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#122
,
|
|
|
Этого будет мало
![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#123
,
|
|
|
Цитата D_KEY @ А что особенного в поведении ссылок, кроме продления жизни временным объектам?Этого будет мало ![]() Сдается мне, что в плюсах и так не существует ссылочного типа. ![]() ![]() ![]() #include <iostream> #include <typeinfo> using namespace std; int main() { const int& a1 = 10; const int a2 = 10; cout << (typeid(a1) == typeid(a2)); return 0; } Типы идентификаторов a1 и a2 одинаковы. Расходимся. Кстати, зачем запретили для ссылок sizeof и получение указателя? Было бы логично выполнять эти операции для объекта, на который указывает ссылка? А то сейчас ссылка в плюсах похожа на симлинк, а в идеале должна быть похожа на хардлинк. Добавлено Хотя нет. Скорее симлинк - это указатель, а хардлинк - ссылка. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#124
,
|
|
|
Цитата applegame @ Типы идентификаторов a1 и a2 одинаковы. Так я про то и говорю всю тему ![]() Цитата Расходимся. А теперь поработай над самим типом в статике ![]() Цитата Кстати, зачем запретили для ссылок sizeof и получение указателя? Было бы логично выполнять эти операции для объекта, на который указывает ссылка? Так и есть ![]() Добавлено В смысле оно и работает так, как ты хочешь. Т.е. в язык зачем-то добавили тип, а затем прописали для него кучу правил, которая фактически приводит к тому, что он ведёт себя не как тип в очень многих случаях. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#125
,
|
|
|
Цитата D_KEY @ Т.е. в язык зачем-то добавили тип D_KEY, сколько раз мне ещё нужно написать, что ссылка не является полноценным типом, чтобы ты, наконец, смог это прочитать это так, как написано? ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#126
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ Т.е. в язык зачем-то добавили тип D_KEY, сколько раз мне ещё нужно написать, что ссылка не является полноценным типом, чтобы ты, наконец, смог это прочитать это так, как написано? ![]() Я тебе сказал, что нужно делать ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#127
,
|
|
|
Цитата applegame @ В данном случае не можешь, потому что контекст разный и споры разные. Ну а я считаю иначе. ![]() Цитата applegame @ Не выкручивайся. Ты же сказал, что продемонстрировал то о чем говорит Qraizer, а оказалось наоборот. Я продемонстрировал, как компилятор может оптимизировать ссылки и не оптимизировать указатели в схожих ситуациях. Я не знаю, что ты там увидел, но показывал я именно это. И ассемблерный код это подтверждает. Цитата applegame @ Ага, и ты именно так и сделал. Да нет. Я явно сказал компилятору, что можно, а что нельзя, причём корректными средствами. А не с помощью злобных кастов от одного к другому. Понятно, что можно (при желании) сделать ссылку на null, и две разные ссылки на одну область памяти с разными типами. Но это всё как раз из серии хаков и говнокода. Батенька, тут показано именно то, о чём я говорил. ![]() ![]() ![]() ![]() ![]() #include <cstdio> struct Val { int val; }; Val GetVal() { return Val{20}; } void Refs1() { volatile int a = 10; const Val& b = GetVal(); const volatile int* volatile c = &b.val; std::printf("%d", a); std::printf("%d", b.val); std::printf("%d", *c); std::printf("%p", c); } С чего бы это? Ведь ссылка - это не более, чем сахарный константный указатель? ![]() Цитата applegame @ Или он и так не считает? если я обявлю две переменные int& и int, будет ли компилятор считать, что их типы разные? Вроде ты сам на этот вопрос ответил. ![]() Цитата applegame @ Что правда? Ну давай расскажи, как можно схлопотать проблемы с pointer aliasing не говнокодя и как ссыоки помогут бороться с этими проблемами. Бинарную десериализацию никогда не писал? ![]() Цитата applegame @ То есть ты намеренно смухлевал? Расскажи еще, что ты знал, что ссылки на временные объекты возвращаемые из функций нельзя биндить даже к константным ссылкам. Ты, похоже, неправильно прочитал собою же процитированное из стандрата. Ты же сам привёл пример (https://ideone.com/CkeMhZ ), где константная ссылка прекрасно "держит" временный объект, возвращённый функцией. Добавлено Цитата D_KEY @ Приведи пруфы. Пруфы чего? А могу я попросить тебя привести пруфы того, что ссылка (в c++) - это самостоятельный тип? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#128
,
|
|
|
Цитата D_KEY @ Ну разве что зачем-то раpрешены странные конструкции типа таких:А теперь поработай над самим типом в статике ![]() ![]() ![]() template<typename T> struct A { T a; }; template<typename T> struct A<T&> { T b; }; и ![]() ![]() typedef int& T; Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#129
,
|
|
|
Цитата applegame @ Ну разве что зачем-то раpрешены странные конструкции типа таких: Ну, когда ты разбираешь декларацию функции, где какой-то параметр может быть помечен ссылкой, то таки да, у тебя будет срабатывать вторая специализация. Ну а затайпдефить ты можешь что угодно. Тут так же, как и с указателями - несмотря на то, что "указатель" относится к декларации (а не к типу), ты можешь затайпдефить его и использовать. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#130
,
|
|
|
Цитата Flex Ferrum @ Тут так же, как и с указателями - несмотря на то, что "указатель" относится к декларации (а не к типу), ты можешь затайпдефить его и использовать. ![]() Указатели являются типом. И, в отличие от ссылок, типом полноценным. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#131
,
|
|
|
Цитата D_KEY @ Указатели являются типом. И, в отличие от ссылок, типом полноценным. Да? А пруф можно? ![]() ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#132
,
|
|
|
Цитата Flex Ferrum @ Пруфы чего? Того, что ссылка является, как ты выразился, модификатором типа. Хотя ты и сам знаешь, что в стандарте этого нет ![]() Цитата А могу я попросить тебя привести пруфы того, что ссылка (в c++) - это самостоятельный тип? Что такое самостоятельный тип? И чем он отличается от несамостоятельного? Ты считаешь, что в C++ нет типа int&? Или что? Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#133
,
|
|
|
Цитата D_KEY @ Что такое самостоятельный тип? И чем он отличается от несамостоятельного? Забудь. Приведи пруфы того, что ссылка в C++ - это тип (в твоём понимании). ![]() Цитата D_KEY @ Ты считаешь, что в C++ нет типа int&? Я считаю, что в C++ есть тип int (относится к категории фундаментальных), и что есть декларации, тип которых может быть "ссылка на тип int". Это знаешь, как у Хайдеггера (в переводе) термин "бытие" может использоваться в пяти разных смыслах. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#134
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ Указатели являются типом. И, в отличие от ссылок, типом полноценным. Да? А пруф можно? ![]() Цитата 8.3.1 Pointers 1 In a declaration T D where D has the form * attribute-specier-seqopt cv-qualier-seqoptD1 [dcl.ptr] and the type of the identier in the declaration T D1 is derived-declarator-type-list T,then the type of the identier of D is derived-declarator-type-list cv-qualier-seq pointer to T. Цитата Может ещё и константность типом является? ![]() const int является типом, да. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#135
,
|
|
|
D_KEY, ты ответь. const в С++ - это тип или нет? А volatile? А массив? А функция?
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#136
,
|
|
|
Цитата Flex Ferrum @ Я считаю, что в C++ есть тип int (относится к категории фундаментальных), и что есть декларации, тип которых может быть "ссылка на тип int". Тогда почему я могу специалищировать шаблон класса, например, типом int&, если это не тип? Почему я могу указать int& везде(ну почти, есть исключения), где требуется указать тип? Цитата Это знаешь, как у Хайдеггера (в переводе) термин "бытие" может использоваться в пяти разных смыслах. ![]() С Хайдеггером у меня не задалось... Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#137
,
|
|
|
Цитата D_KEY @ const int является типом, да. Является типом декларации. Говорить при этом, что const является типом - нельзя. Есть декларация, есть некий тип1 (из категории fundamental или compound), и есть некий тип2, который тип1 с навешанными на него дополнительными характеристиками (константность, волатильность, ссылочность, и прочее). Тип1 - это из системы типов, а тип2 - это тип конкретной декларации. Ссылки не входят в множество того, что является типом1. Но они могут быть навешаны на него и произвести тип2. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#138
,
|
|
|
Цитата Flex Ferrum @ D_KEY, ты ответь. const в С++ - это тип или нет? А volatile? А массив? А функция? const int - тип. Так же как int[100500]. И int&, про который я и спрашиваю, зачем он существует как тип. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#139
,
|
|
|
Цитата D_KEY @ Тогда почему я могу специалищировать шаблон класса, например, типом int& Ты можешь его и сигнатурой функции специализировать. ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#140
,
|
|
|
Цитата Flex Ferrum @ Может тебе напомнить, забывчивый ты наш? Я продемонстрировал, как компилятор может оптимизировать ссылки и не оптимизировать указатели в схожих ситуациях. Я не знаю, что ты там увидел, но показывал я именно это. И ассемблерный код это подтверждает. ![]() Цитата Flex Ferrum @ И тобой было продемонстрировано именно то что имел в виду Qraizer? Как ссылка запретила компилятору многие оптимизации? Ты всего лишь продемонстрировал, как volatile запрещает компилятору оптимизировать доступ к переменной. Правда непонятно зачем, потому что для этого volatile и было придумано.Цитата Qraizer @ Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Что и было мною продемонстрировано на примерах. Цитата Flex Ferrum @ Ну и я сделал, тоже корректными средствами, без злобных кастов, ссылка перестала оптимизироваться.Да нет. Я явно сказал компилятору, что можно, а что нельзя, причём корректными средствами. А не с помощью злобных кастов от одного к другому. Цитата Flex Ferrum @ Компилятор особо ничего не решал, у него не было выбора. Да и ссылка, которая превратилась во временный объект, совсем не соптимизировалась, а реализация в коде полностью совпадает с указателем. Бу-га-га-га.Батенька, тут показано именно то, о чём я говорил. ![]() ![]() ![]() Цитата Flex Ferrum @ Я имел ввиду реализацию. Компилятор внутри реализует ссылку как указатель, который может соптимизироваться, а может и нет. Что тебе было продемонстрировано в примере. В очень многих случаях указатель может полностью заменить ссылку. Только при удержании временных объектов ссылка ведет себя по иному. Ну и я уже соглашался с тобой, что концептуально ссылка - это псевдоним.С чего бы это? Ведь ссылка - это не более, чем сахарный константный указатель? ![]() Цитата Flex Ferrum @ Писал много раз. Крайний раз MessagePack. Никаких проблем не было.Бинарную десериализацию никогда не писал? ![]() Ну и, все-таки, хотелось бы маленький, но конкретный пример. Типа вот тут проблема с pointer aliasing из-за указателя. Меняем его на ссылку и вуаля, проблема ушла. Для простоты, разрешается даже говнокод с мутными кастами. Цитата Flex Ferrum @ Я все прочитал правильно. Речь шла не о просто временных объектах, а о ссылках на временные объекты возвращаемые из функции. Или ты издеваешься, или какое-то недопонимание между тобой и мной.Ты, похоже, неправильно прочитал собою же процитированное из стандрата. Ты же сам привёл пример (https://ideone.com/CkeMhZ ), где константная ссылка прекрасно "держит" временный объект, возвращённый функцией. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#141
,
|
|
|
Цитата Flex Ferrum @ Цитата D_KEY @ const int является типом, да. Является типом декларации. Говорить при этом, что const является типом - нельзя. Есть декларация, есть некий тип1 (из категории fundamental или compound), и есть некий тип2, который тип1 с навешанными на него дополнительными характеристиками (константность, волатильность, ссылочность, и прочее). Тип1 - это из системы типов, а тип2 - это тип конкретной декларации. Ссылки не входят в множество того, что является типом1. Но они могут быть навешаны на него и произвести тип2. Откуда ты это взял? Найди пруф на это. Цитата 3.9 Types 1 [Note: 3.9 and the subclauses thereof impose requirements on implementations regarding the representation of types. There are two kinds of types: fundamental types and compound types. Types describe objects (1.8), references (8.3.2), or functions (8.3.5). end note] Цитата 3.9.2 Compound types 1 Compound types can be constructed in the following ways: (1.1) arrays of objects of a given type, 8.3.4; (1.2) functions, which have parameters of given types and return void or references or objects of a given type, 8.3.5; (1.3) pointers to void or objects or functions (including static members of classes) of a given type, 8.3.1; (1.4) references to objects or functions of a given type, 8.3.2. There are two types of references: (1.4.1) lvalue reference (1.4.2) rvalue reference ... Добавлено А если все, как ты говоришь, тогда C++ - ещё более лютое говно, чем я думал ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#142
,
|
|
|
Договоритесь, что под "тип ссылка" имеется в виду "ссылочный тип", то бишь композитный тип, в котором ссылка скомбинирована с фундаментальным или композитным типом. А то слово "ссылка" может быть воспринята как псевдоним, а не тип.
Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
![]() |
Сообщ.
#143
,
|
|
Цитата applegame @ Возвращаю: когда оппонент выцепляет непринципиальную пару слов в двухабзацном посте и на протяжении трёх ответов игнорирует эти оставшиеся два абзаца, полностью зациклившись на непринципиальных двух словах, он, мягко говоря, демонстрирует свою полную некомпетентность в вопросе, о котором спорит. Был бы на твоём месте троль, реакция была бы другой, ну а иначе... ты ожидал чего-то, кроме фэйсплма? Все равно твоя аргументация сводится к отсылкам к собственным постам (в том числе в весьма отдаленном прошлом), к фейспалмами и советам пойти куда-нибудь далеко учить матчасть. Такую "аргументацию" оставь при себе. Добавлено Цитата applegame @ ЧЁ??Эм... но коментс, Qraizer, говорил, о том, что, в отличие от указателей, ссылки помогают избежать опасных агрессивных оптимизаций. Добавлено P.S. Надеюсь, ты обиделся именно на посыл в 8 класс. Это уже вообще ни в какие ворота. Добавлено Цитата Flex Ferrum @ Зачем? Ты это уже прекрасно продемонстрировал и без всяких полей. Агрессивная оптимизация к ссылкам применима легче, чем к указателям. Я упомянул поля в классах, потому что их инициализация выполняется всегда (в случае указателей необязательно) в конструкторах, а используются они в подавляющем большинстве случаев в остальных методах, и это сильно разные точки в общем потоке исполнения программы, и они не расположены в пределах некоего одного блока функции/метода. В случае ссылок компилятор – для уже сконструированного экземпляра – всегда уверен в их значениях и никогда не может быть уверен в значениях указателей.Поясни примером кода, что ты имеешь в виду. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#144
,
|
|
|
Цитата Qraizer @ Я тогда хз, как понимать вот эту твою. фразу, ЧЁ??Эм... но коментс, Цитата Qraizer @ Я это понял так, что по твоему ссылки позволяют применять оптимизации, которые с указателями могут вызвать проблемы с pointer aliasing. Что не так?Если интересно и ещё не в курсе, почитай в гугле на тему "pointer aliasing". Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Которые доступны при замене указателей на ссылки, Цитата Qraizer @ Какой злой. Но я на тебя не обижаюсь. P.S. Надеюсь, ты обиделся именно на посыл в 8 класс. Это уже вообще ни в какие ворота. ![]() Цитата Qraizer @ В равных условиях не легче. Флекс явно запретил оптимизацию для указателя и заявил: "вот смотрите компилятор не смог оптимизировать указатель!". Ваша наглость не знает границ, господа. На всякий случай еще раз код:Зачем? Ты это уже прекрасно продемонстрировал и без всяких полей. Агрессивная оптимизация к ссылкам применима легче, чем к указателям. ![]() ![]() #include <cstdio> void Refs1() { volatile int a = 10; volatile int& b = a; volatile int* volatile c = &b; // волатильный указатель - явный запрет оптимизации std::printf("%d", a); std::printf("%d", b); std::printf("%d", *c); std::printf("%p", c); } Цитата Qraizer @ Ну вот давай без эмоций и посыланий в 8-й класс. Может я и правда чего-то не знаю в плюсах. Но константный указатель тоже нужно обязательно инициализировать в конструкторе. Иначе как объяснить, что этот код не компилируется:Я упомянул поля в классах, потому что их инициализация выполняется всегда (в случае указателей необязательно) в конструкторах https://glot.io/snippets/erji17fi8u ![]() ![]() class Foo { int* const c; }; int main() { Foo foo; } Цитата Qraizer @ Но ведь в случае константных указателей компилятор тоже будет уверен. Не так ли? Без фейспалмов, скажи, так это или не так? Смотри вышеприведенный код. В случае ссылок компилятор – для уже сконструированного экземпляра – всегда уверен в их значениях и никогда не может быть уверен в значениях указателей. Добавлено То о чем говорил D_LEY: Цитата Stroustrup. Why does C++ have both pointers and references? C++ inherited pointers from C, so I couldn't remove them without causing serious compatibility problems. References are useful for several things, but the direct reason I introduced them in C++ was to support operator overloading. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#145
,
|
|
|
Знаете, что показала тема?
Что даже одни из самых адекватных и имеющих хороший профессиональный уровень форумчан не в состоянии вести нормальную дискуссию с аргументацией, признанием ошибок и без перехода на личности. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#146
,
|
|
|
На самом деле в C++ существует несколько разновидностей ссылок, требующих разного подхода к их реализации
Навскидку Ссылки первой разновидности ссылаются на объекты, к которым и без них можно обратиться. Их ещё называют псевдонимами. Обычно компилятор не выделяет для таких ссылок память, а напрямую обращается к объекту ссылки. Впрочем, при оптимизации компилятор может захешировать такую ссылку, как впрочем может захешировать любой другой часто используемый адрес. Ссылки второй разновидности, ссылающиеся на некоторый объект, доступный только в момент инициализации ссылки (например, конструируемый или получаемый из какой-нибудь функции). Такие ссылки сходны с обычным константным указателем, с автоматическим разыменованием, и возможным вызовом деструктора в конце области видимости. Ссылки, передающие значения в функцию, возвращающие их из функции. Могут иметь lvalue или rvalue-семантику. Нужны для того, чтобы без нужды не копировать сложные объекты, для реализации полиморфизма. Пожалуй, обладают самым сложным поведением из всех. Ссылки, являющиеся частью составных объектов. Эти похожи на вторую разновидность. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#147
,
|
|
|
Тут по тырнетам ходит цитата Страуструпа:
Цитата Очевидной реализацией ссылки является (константный) указатель, при каждом использовании которого происходит разыменование. В некоторых случаях компилятор может оптимизировать ссылку таким образом, что во время исполнения вообще не будет существовать объекта, представляющего ссылку. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#148
,
|
|
|
Цитата applegame @ И тобой было продемонстрировано именно то что имел в виду Qraizer? Как ссылка запретила компилятору многие оптимизации? Ты всего лишь продемонстрировал, как volatile запрещает компилятору оптимизировать доступ к переменной. Правда непонятно зачем, потому что для этого volatile и было придумано. Давай я напомню тебе, что именно написал Qraizer: Цитата Qraizer @ В общем случае не может. Даже больше: может в ограниченном количестве случаев. Всё потому, что указатель доступен программисту как есть, поэтому компилятор не может гарантировать, кто где-то, в невидимом ему контексте, этот указатель программером не поменяется, даже если всё время жизни объекта-указателя у него перед глазами. ... Учёт этой штуки по факту заставляет компилятор запрещать многие оптимизации. Которые доступны при замене указателей на ссылки, т.к. единственное место, где ссылка может поменять своё значение – это точка её инициализации. То есть, суммируя, ссылки позволяют компилятору более агрессивно оптимизировать опираясь на их свойства. И константные указатели (о которых ты говоришь) тут не могут являться адекватной заменой, но об этом чуть позже. Поэтому да, мой код показал именно то, о чём говорит Qraizer. Стоило мне сделать "уточнение" для компилятора, что значение указателя может поменяться за пределами области видимости - и усё, ему пришлось отложить свой оптимизатор в сторону. В отношении указателей. А вот написать эквивалентный код со ссылкой уже не выйдет. Именно по причине того, что сделать ссылку волатильной (то есть изменяемой за пределами контекста видимости и использования) - нельзя при всём желании. Цитата applegame @ Ну и я сделал, тоже корректными средствами, без злобных кастов, ссылка перестала оптимизироваться. Только твой пример не эквивалентен моему. В моём примере указатель и ссылка ссылаются на один и тот же объект, видимый в этом же контексте. В твоём - ты указатель инициализируешь адресом локальной переменной, а ссылку биндишь к временному объекту в динамической памяти. И таки да. Ты показал, что ссылка может "держать" этот объект до момента окончания использования, что и требует стандарт. Но обрати внимание на твой и на мой пример. В твоём примере ссылка превращается в указатель (ну да, временный объект - это ведь указатель на распределённую память). В моём - ссылка уже сам объект. Можно ещё кейсов набрать, где ссылки будут во что-то ещё превращаться. Всё это показывает лишь то, что компилятор интерпретирует ссылку согласно контексту использования, что и требуется. Цитата applegame @ Компилятор внутри реализует ссылку как указатель, который может соптимизироваться, а может и нет. Большая ошибка так считать. Мы с тобой уже в этой дискуссии набрали разных примеров того, как поступает компилятор со ссылками на разных уровнях оптимизации. Реализация "как указатель" - лишь одна из возможных, но не единственная. И не может быть единственная. Да и, с другой стороны, какая разница, что там думает себе компилятор в каждом конкретном случае? Речь по большей части о видимой (и стандартизованной) семантики этой сущности, а интерпретация конкретным компилятором - это детали реализации, тем более, что: Цитата 8.3.2 References (dcl.ref) 4 It is unspecified whether or not a reference requires storage Цитата applegame @ Ну и, все-таки, хотелось бы маленький, но конкретный пример. Типа вот тут проблема с pointer aliasing из-за указателя. Меняем его на ссылку и вуаля, проблема ушла. Зачем тебе такой пример? Указатель не всегда можно заменить на ссылку и наоборот. Это разные сущности с разным поведением. Цитата applegame @ Я все прочитал правильно. Речь шла не о просто временных объектах, а о ссылках на временные объекты возвращаемые из функции. Или ты издеваешься, или какое-то недопонимание между тобой и мной. А, всё. Понял. ![]() ![]() Цитата applegame @ Пикантности добавляет тот факт, что волатильный указатель сам по себе - достаточно бесполезная штука и в реальной жизни вряд ли встречается. Угу. А потом на сцену выходит многопоточность и прочие забавные вещи. Впрочем, ты прав. Вместо волатильных указателей лучше использовать атомик-указатели. Ну, как минимум. ![]() Цитата applegame @ Но ведь в случае константных указателей компилятор тоже будет уверен. Не так ли? Не так. Константность указателя говорит лишь о том, что его значение не поменяется в области видимости константности. Но константность в рамках конкретного скоупа ничего не говорит о том, что указатель на самом деле не будет менять своё значение даже в рамках этого скоупа. Про ссылки такие допущения делать можно. Вот пример: ![]() ![]() class RotationLog { public: //... void Trace(const std::string& message) const { (*m_os) << message << std::endl; // Тут указатель на m_os - константный. } void Rotate() { // ... if (RotationCriteriaMet()) m_curStream.reset(new std::ofstream(GetNewFileName()); // тут m_os - не константный // ... } private: std::unique_ptr<std::ofstream> m_curStream; }; Теперь представим себе, что Rotate крутится в отдельном потоке, а Trace - вызывается из множества других. Какие предположения может делать компилятор об неизменности константного указателя в методе Trace? Ровным счётом никаких кроме тех, что Trace значение указателя не изменит. Исправление этого кода - простое. Добавить мьютекс, указатель делать шареным и под мьютексом снимать его копию в методе Trace, а в Rotate под ним же ресеттить. К слову, поменять здесь указатель на ссылку - нельзя. Добавлено Цитата D_KEY @ Откуда ты это взял? Найди пруф на это. Да, тут ты прав. А я - нет. ![]() ![]() Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#149
,
|
|
|
Цитата Flex Ferrum @ Окай. Хорошо, согласен, я не совсем верно интерпретировал слова Qraizer'a. И прошу у него прощения за непреднамеренное искажение смысла.авай я напомню тебе, что именно написал Qraizer: Цитата Flex Ferrum @ А ты посмотри с другой стороны: волатильный указатель в принципе нельзя заменить ссылкой. Иначе его волатильность получается бессмысленой. То есть в данном случае заставить компилятор применить оптимизацию путем замены волатильного указателя ссылкой не получится, просто потому что такую замену сделать невозможно. Если же его волатильность липовая, до достаточно просто её убрать и оптимизация будет такая же как и с ссылкой. Ссылка в данном случае либо невозможна либо бесполезна.Стоило мне сделать "уточнение" для компилятора, что значение указателя может поменяться за пределами области видимости - и усё, ему пришлось отложить свой оптимизатор в сторону. В отношении указателей. А вот написать эквивалентный код со ссылкой уже не выйдет. Именно по причине того, что сделать ссылку волатильной (то есть изменяемой за пределами контекста видимости и использования) - нельзя при всём желании. Цитата Flex Ferrum @ Да, и выяснили, что в основном компилятор поступает с сылками также как и с указателями, за некоторыми исключениями вроде волатильности и изменения времени жизни объектов на которые эта ссылка указывает.Большая ошибка так считать. Мы с тобой уже в этой дискуссии набрали разных примеров того, как поступает компилятор со ссылками на разных уровнях оптимизации Цитата Flex Ferrum @ С этим согласен.Да и, с другой стороны, какая разница, что там думает себе компилятор в каждом конкретном случае? Речь по большей части о видимой (и стандартизованной) семантики этой сущности, а интерпретация конкретным компилятором - это детали реализации, тем более, что: Цитата Flex Ferrum @ Стоп, стоп, стоп. Мы говорим о константных указателях - членах класса. В их константности компилятор может быть уверен всегда. Нет? Кстати в D эта проблема решается дополнительным модификатором immutable. Этот модификатор гарантирует компилятору, что переменная не будет меняться нигде и никогда (в том числе и других потоках) пока не выйдет из всех областей видимости.Не так. Константность указателя говорит лишь о том, что его значение не поменяется в области видимости константности. Но константность в рамках конкретного скоупа ничего не говорит о том, что указатель на самом деле не будет менять своё значение даже в рамках этого скоупа. Про ссылки такие допущения делать можно. Цитата Flex Ferrum @ В этом-то и прикол. Если указатель должен меняться, то его априори нельзя заменить на ссылку. А если же не должен, то можно, но никакого профита с точки зрения оптимизации это не даст. Опять мы приходим к тому, что замена указателя на ссылку не поможет компилятору применить оптимизации.К слову, поменять здесь указатель на ссылку - нельзя. Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#150
,
|
|
|
Цитата applegame @ А ты посмотри с другой стороны: волатильный указатель в принципе нельзя заменить ссылкой. Иначе его волатильность получается бессмысленой. То есть в данном случае заставить компилятор применить оптимизацию путем замены волатильного указателя ссылкой не получится, просто потому что такую замену сделать невозможно. Если же его волатильность липовая, до достаточно просто её убрать и оптимизация будет такая же как и с ссылкой. Ссылка в данном случае либо невозможна либо бесполезна. В данном конкретном синтетическом примере волатильность была применена для того, чтобы отключить оптимизатор на коротком участке программы. В реальности с высокой долей вероятности получится, что сферы использования указателей и ссылок будут сильно различаться. Причём указатели будут использоваться в гораздо более широких скоупах (нередко - совпадающих со скоупом всей программы), чем ссылки, именно за счёт своей овеществлённости. При таком раскладе предсказать возможность изменения (или неизменения) значения указателем становится сильно сложнее. А вот скоупы использования ссылок будут чаще всего уже (блок, функция или модуль), а потому и у компилятора информации может быть больше. Цитата applegame @ Да, и выяснили, что в основном компилятор поступает с сылками также как и с указателями, за некоторыми исключениями вроде волатильности и изменения времени жизни объектов на которые эта ссылка указывает. Только это не исключения. А если добавить в рассматриваемый контекст ещё и правые ссылки, то совсем не исключения. Механизм правых ссылок на указателях вообще реализовать нельзя. Как и некоторые свойства левых ссылок. Что ещё раз говорит, что это не эквивалентные сущности. Цитата applegame @ Мы говорим о константных указателях - членах класса. В их константности компилятор может быть уверен всегда. Нет? Строго говоря - нет. Потому что есть const_cast, который к ссылкам (при всём желании) не применим. А за счёт неопределённости (в стандарте) на счёт того, занимают ссылки какое-то место или нет, ты даже с помощью грязных хаков сможешь поменять значения только тех ссылок, в которых ты точно уверен, что это засахаренные указатели. Цитата applegame @ Опять мы приходим к тому, что замена указателя на ссылку не поможет компилятору применить оптимизации. В такой формулировке - да. Только вот начальный тезис был чуть другой: ссылки позволяют компилятору более агрессивно оптимизировать за счёт прибитой гвоздями иммутабельности и некоторых других свойств, которых у указателей нет. Только из этого тезиса не следует, что одно можно заменить другим. ![]() Сообщения были разделены в тему "Баллада о ссылках в С++" Это сообщение было перенесено сюда или объединено из темы "D vs C++" |
Сообщ.
#151
,
|
|
|
Цитата Flex Ferrum @ То есть, говорить о пользе замены указателей на ссылки и наоборот с точки зрения оптимизации достаточно бессмысленно. Выбор между указателем и ссылкой дожен происходить с других точек зрения, например, безопасности или необходимости в свойствах недоступных собрату. Так сказать, указателю - указателево, а ссылке - ссылково. Указатели с большим скоупом в большинстве случаев вообще передаются по значению и их мутабельность/иммутабельность не важна совершенно.В данном конкретном синтетическом примере волатильность была применена для того, чтобы отключить оптимизатор на коротком участке программы. В реальности с высокой долей вероятности получится, что сферы использования указателей и ссылок будут сильно различаться. Причём указатели будут использоваться в гораздо более широких скоупах (нередко - совпадающих со скоупом всей программы), чем ссылки, именно за счёт своей овеществлённости. При таком раскладе предсказать возможность изменения (или неизменения) значения указателем становится сильно сложнее. А вот скоупы использования ссылок будут чаще всего уже (блок, функция или модуль), а потому и у компилятора информации может быть больше. Цитата Flex Ferrum @ А разве изменение такого констатного мембера класса по стандарту не UB? И хотя стандарт не требует выделения места под ссылку, подозреваю, что ссылки-члены класса вседа будут "засахаренными" Строго говоря - нет. Потому что есть const_cast, который к ссылкам (при всём желании) не применим. Цитата Flex Ferrum @ В этом плане да. Даже если компилятор мог оптимизировать указатель, но программист добавил изменение значения такого указателя, то оптимизация будет отменена. С ссылками такое не прокатит. Но опять же такой указатель на ссылку не заменишь.А за счёт неопределённости (в стандарте) на счёт того, занимают ссылки какое-то место или нет, ты даже с помощью грязных хаков сможешь поменять значения только тех ссылок, в которых ты точно уверен, что это засахаренные указатели. Цитата Flex Ferrum @ Ну в тезисе Qraizer'а замена указателей на ссылки таки присутствовала, ну да ладно, может быть он имел в виду именно то, о чем ты говоришь.В такой формулировке - да. Только вот начальный тезис был чуть другой: ссылки позволяют компилятору более агрессивно оптимизировать за счёт прибитой гвоздями иммутабельности и некоторых других свойств, которых у указателей нет. Эта тема была разделена из темы "D vs C++" |
Сообщ.
#152
,
|
|
|
Цитата applegame @ То есть, говорить о пользе замены указателей на ссылки и наоборот с точки зрения оптимизации достаточно бессмысленно. Ну как бы да. Да и речь начиналась именно с обсуждения их свойств с точки зрения оптимизации, а не замены одного на другое. А так, как мы выяснили, семантически (с точки зрения исходного текста и его понимания разработчиком, и стандарта) константный указатель не является эквивалентом ссылки в силу разницы в свойствах. Цитата applegame @ Так сказать, указателю - указателево, а ссылке - ссылково. Именно так. Более того, согласно Core Guidelines крен уже идёт в сторону не просто указателей, а умных указателей. То есть в С++-программе должны быть либо ссылки, либо unique/shared/xxx_ptr. Цитата applegame @ А разве изменение такого констатного мембера класса по стандарту не UB Угу. Но кого и когда это останавливало? Кроме того, стандарт говорит "вообще" об изменениях константных объектах. Если ты точно знаешь, что объект никогда не будет настолько константным, чтобы быть размещённым в защищённых от записи областях памяти, то трюки с const_cast вполне допустимы. Но их применение нередко указывает на проблемы в дизайне. |
Сообщ.
#153
,
|
|
|
Цитата Flex Ferrum @ Не знаю с чего оно там начиналось Похоже каждый начал обсуждать что-то свое.Да и речь начиналась именно с обсуждения их свойств с точки зрения оптимизации, а не замены одного на другое. И все-таки, не мог бы ты отделить обсуждение ссылок в отдельную холиварную тему? |