, что адреса у str1 и str2 все же разные, давай теперь разберёмся, что же у них одинаковое и почему.
Как не трудно увидеть из объявления str1 и str2 — это указатели. И как и все указатели, они обладают присущей всем указателям двойственностью — есть собственно объект указателя и у этого указателя есть значение — адрес какого-то объекта, располагающегося где-то в памяти. Так вот, в случае str1 и str2 — это два разных объекта с разными адресами, но с одинаковыми значениями. А почему же значения этих указателей оказались одинаковыми? Чтобы ответить на этот вопрос, нужно заглянуть в стандарт языка С++, в раздел String literals:
9 Evaluating a string-literal results in a string literal object with static storage duration ([basic.stc]).
[Note 4: String literal objects are potentially non-unique ([intro.object]). Whether successive evaluations of a string-literal yield the same or a different object is unspecified.
— end note]
Ключевое я выделил. Как видишь, стандарт не запрещает разным строковым литералам быть ассоциированными с одним и тем же объектом, но и не гарантирует, что это будет именно так. То есть, компилятор может решать этот вопрос по своему усмотрению. Так что, то, что они совпали в данном конкректном случае, можешь считать счастливой случайностью.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Shmj, Вы писали:
Pzz>>"Просто для себя знайте..." — это в спецификации языка так написано и проверяется компилятором, или негласная договорённость среди посвященных?
S>Компилятор гарантирует что объекты с константные одинаковыми данными — будут иметь один и тот же адрес. А остальное — построение дерева — это уже не язык а отдельная мощная библиотека. Так вот — если передаете const — оно не будет вызывать build второй раз. Хотите без оптимизации — делайте без const.
При чем тут оптимизация?
Ты сказал, что компилятор может не вызывать метод объекта, если у него уже есть такой же объект (или если он уже вызывал такой метод). У меня это вызывает очень большие сомнения.
Здравствуйте, rg45, Вы писали:
R>Как не трудно увидеть из объявления str1 и str2 — это указатели. И как и все указатели, они обладают присущей всем указателям двойственностью — есть собственно объект указателя и у этого указателя есть значение — адрес какого-то объекта, располагающегося где-то в памяти. Так вот, в случае str1 и str2 — это два разных объекта с разными адресами, но с одинаковыми значениями. А почему же значения этих указателей оказались одинаковыми? Чтобы ответить на этот вопрос, нужно заглянуть в стандарт языка С++, в раздел String literals:
Это и так понятно.
R>Ключевое я выделил. Как видишь, никто нам не гарантирует, что значения str1 и str2 будут совпадать. То, что они совпали в данном случае, можешь считать счастливой случайностью.
Не случайность а оптимизация. Но подобные оптимизации в C++ возможны только для строк, для более сложных constexpr — так же могли бы сделать в теории, но пока не смогли на практике.
Здравствуйте, Pzz, Вы писали:
Pzz>При чем тут оптимизация? Pzz>Ты сказал, что компилятор может не вызывать метод объекта, если у него уже есть такой же объект (или если он уже вызывал такой метод). У меня это вызывает очень большие сомнения.
Не компилятор — а основной фреймворк — Flutter — проводит такую оптимизацию — при перестроении дерева проверят изменился ли адрес — если не изменился — то ветку не перестраивает а оставляет все как было. Const — не изменяются никогда, даже будут добавлены заново (новые оъекты) с теми же значениями.
Здравствуйте, Shmj, Вы писали:
S>Не случайность а оптимизация. Но подобные оптимизации в C++ возможны только для строк, для более сложных constexpr — так же могли бы сделать в теории, но пока не смогли на практике.
Откуда у тебя уверенность, что подобные оптимизации невозможны для других типов? Компилятор может применять любые оптимизации, если это не меняет видимого поведения программы — вплоть до того, что вообще не создавать каких-то объектов, которые фигурируют в исходном тексте программы. Но только к твоему случаю это не относится — ты ведь выводишь на печать адреса объектов, а они обязаны быть разными. Соответственно компилятор не может применить подобную оптимизацию в данном случае. Своего рода эффект наблюдателя.
P.S. Тьфу, блин, всё-таки, втянул ты меня в свою болтологию.
P.P.S. И кстати, в твоём примере компмилер запросто может вывести на экран два фейковых адреса, где ПРЕДПОЛОЖИТЕЛЬНО могли БЫ быть созданы твои объекты, а создание самих объектов проскипать. Опять же, если это не меняет видимого поведения программы. И обнаружить ты это можешь только заглянув в объектный код.
Это я написал, не подумав. Не может он поскипать создание объектов, потому что не видит, каким образом эти адреса используются в basic_ostream::opeartor<<.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Откуда у тебя уверенность, что подобные оптимизации невозможны для других типов?
Вот если бы была гарантия хотя бы для constexpr с одинаковыми данными... Не так уж сложно добавить словарик и в момент компиляции не создавать лишнего.
, понял как лучше донести.
R>А я было уже подумал: "вот молодец, не засирает профильный форум". Но не в этот раз, походу.
Rg45!
Ну ты блин, оптимист!
"Не засирает..." Ага! Щазззз!!!
Всё ж просто: ты когда читал пост? Ага в 21::25...
N>Скоро узнаешь о концепции COW, восхитишься, начнёшь применять. Потом поймаешь тормоза в многопоточке, разберёшься и откажешься. И начнёшь использовать всё по месту и по необходимости.
S>....как-то не задумывался что это может иметь такие последствия.
Такое ощущение, что наш достославный Шмыджик, пишет код только на бумажке. И, кстати, отлаживает его также... На бумажке...
Тогда всё сходится. Хулио там задумываться?
Здравствуйте, Pzz, Вы писали:
Pzz>А если ты две идентичные строки объявишь в разных единицах трансляции, то это вообще вопрос к линкеру, сводить их или нет (и что-то мне подсказывает, что скорее всего, не сведёт).
В ELF отдельный флаг секции, 'S' для GNU as, есть для объединения NUL-terminated строк. Линкеры его отрабатывают.
Вот для других данных уже не так просто.
Я бы не удивился, если бы где-то делали подсекции с именами согласно хэшу содержимого
C>Такое ощущение, что наш достославный Шмыджик, пишет код только на бумажке. И, кстати, отлаживает его также... На бумажке... C>Тогда всё сходится. Хулио там задумываться?
Хе-хе , Когда-то давно, когда машинное время выделялось всего два часа в неделю, и надо было успеть ввести код, проверить, получить результат и отчитаться, то программировали именно на бумажке. И задумываться надо было вдвойне.
Это сейчас можно педалить любую дичь — тебя ide поправит ещё до вызова компилятора.
N.B. ёлы-палы, какой я старый...
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Shmj, Вы писали:
S>Можно было инициализировать разными данными (номер добавить) — тогда и адреса будут разные.
С уникальными номерами плохо: придётся вручную вести централизованный реестр использованных номеров.
+ Проблемы с библиотеками сторонних поставщиков, плагины (.dll), нумерация в разных единицах трансляции...
Уникальные адреса — проще.
C>>Такое ощущение, что наш достославный Шмыджик, пишет код только на бумажке. И, кстати, отлаживает его также... На бумажке... C>>Тогда всё сходится. Хулио там задумываться?
SVZ>Хе-хе , Когда-то давно, когда машинное время выделялось всего два часа в неделю, и надо было успеть ввести код, проверить, получить результат и отчитаться, то программировали именно на бумажке. И задумываться надо было вдвойне. SVZ>Это сейчас можно педалить любую дичь — тебя ide поправит ещё до вызова компилятора.
SVZ>N.B. ёлы-палы, какой я старый...
Дык и я сложные задачи всегда начинаю на бумажке. А только потом тесты ваять, наброски. А уж потом, только затем...
И дело тут не в двух часах машинного времени.
Просто-напросто такой подход позволяет не впадать в популярнейшую концепцию разработки "хиракс, хиракс ‒ и в продакшен".
Больше раздолья для анализа, ну и погонять в тестовом коде, чтобы прочуйствовать нюансы.
Здравствуйте, Shmj, Вы писали:
S>Тут же не только в том дело, что объект не расходует память и это гарантированно. Важно что можно утверждать что объект не изменился и можно не вызывать повторно его методы.
Плюсовый компилятор и так это делает, если может доказать. А верить программисту на слово, который "мамой клянусь, объект константный, метод вернёт то же самое" компилятору никак нельзя
Здравствуйте, Shmj, Вы писали:
S>Сделали так, чтобы все-таки можно было работать с не-константными внешними объектами, иначе будет очень узкая сфера применения — а сейчас используется на полную. Т.е. просто для себя знать — не делать const, если методы не чистые. Компилятор пока не проверяет.
Здравствуйте, Shmj, Вы писали:
S>Не компилятор — а основной фреймворк — Flutter — проводит такую оптимизацию — при перестроении дерева проверят изменился ли адрес — если не изменился — то ветку не перестраивает а оставляет все как было. Const — не изменяются никогда, даже будут добавлены заново (новые оъекты) с теми же значениями.
Подожди, ты говорил о языке (т.е. компилятор), а теперь говоришь, что это делает библиотека. Что мешает тебе в твоей библиотеке на плюсах заводить поле с флагом, и делать всё то же, что делает библиотека на дарте?
Здравствуйте, пффф, Вы писали:
S>>Не компилятор — а основной фреймворк — Flutter — проводит такую оптимизацию — при перестроении дерева проверят изменился ли адрес — если не изменился — то ветку не перестраивает а оставляет все как было. Const — не изменяются никогда, даже будут добавлены заново (новые оъекты) с теми же значениями.
П>Подожди, ты говорил о языке (т.е. компилятор), а теперь говоришь, что это делает библиотека. Что мешает тебе в твоей библиотеке на плюсах заводить поле с флагом, и делать всё то же, что делает библиотека на дарте?
Не библиотека а фреймворк. Язык обеспечивает идентичность — размещение по одному адресу. А фреймворк уже использует этот факт для супер-оптимизаций.
Здравствуйте, Shmj, Вы писали:
S>Если константный класс (конструктор с const) — то ограничения не касаются тела методов, к сожалению Но просто для себя знайте что такие методы не должны иметь т.н. побочных эффектов. Если допустили побочный эффект — ССЗБ, не нужно было делать const-конструктор.
S>Сделали так, чтобы все-таки можно было работать с не-константными внешними объектами, иначе будет очень узкая сфера применения — а сейчас используется на полную. Т.е. просто для себя знать — не делать const, если методы не чистые. Компилятор пока не проверяет.
Вот ты непрошибаемый. Тебе не приходило в голову, что, если б не твои операции взятия адресов, то компилятор мог бы вообще не создавать никаких объектов? Вот тебе пример, обрати внимание на созданный машинный код:
Когда ты выводишь на печать адреса, компилятор не видит, что происходит с этими адресами внутри РАН-ТАЙМОВОГО std::basic_ostream<char, std::char_traits<char> >::operator<<(int). Поэтому он вынужден честно сгенерировать два РАНТАЙМОВЫХ объекта.
То есть, ты возмущаешься тому, что создаётся два объекта вместо одного в то время, когда вообще никаких объектов не создаётся. И всё из-за твоих невежественных попыток определить количество компайл-тайм объектов, через взятие их адресов! Капец, блин, целую теорию построил на своём невежестве.
--
Справедливость выше закона. А человечность выше справедливости.