Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, rg45, Вы писали:
CS>А можно узнать что именно OK в этом коде:
CS>
CS>const std::string& s2 = function("Happy New Year!"); //OK!
CS>
CS>?
CS>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.
по-идеи в первом случае все будет ок, там кругом ссылка. так же?
второй случай отработает корректно, только если
const std::string& s2 = function(std::string("Happy New Year!"));
поправьте если не прав
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, rg45, Вы писали:
CS>А можно узнать что именно OK в этом коде:
CS>
CS>const std::string& s2 = function("Happy New Year!"); //OK!
CS>
CS>?
"OK" в этом коде то, что ссылка не перестает быть действительной, сразу же после инициализации, как это было бы, если бы существовал только первый вариант перегруженной функции.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Анатолий Широков, Вы писали:
CS>>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.
АШ>А продления времени жизни временного объекта, являющегося результатов выполнения перегруженной функции принимающей rvalue, не видно?
Нет, не видно. Может щательнее надо куда-то смотреть?
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, Анатолий Широков, Вы писали:
CS>>>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.
АШ>>А продления времени жизни временного объекта, являющегося результатов выполнения перегруженной функции принимающей rvalue, не видно?
CS>Нет, не видно. Может щательнее надо куда-то смотреть?
CS>Вот эта программуля
CS>
Падает, вероятно, от того, что у программы не нулевой код возврата, который, по видимому, расценивается как ошибка. Исправим это мелкое недоразумение и вот, уже ничего не падает: url=http://ideone.com/SvJEO
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
CS>>Возвращает 0. Или падает. Как карта ляжет.
R>Падает, вероятно, от того, что у программы не нулевой код возврата, который, по видимому, расценивается как ошибка. Исправим это мелкое недоразумение и вот, уже ничего не падает: url=http://ideone.com/SvJEO
То же самое но в VC++ 2010 проделай.
В ём родимом если написать так (явно)
const std::string& s2 = function(std::string("Happy New Year"));
то срабатывает функция std::string function(std::string&& str);
Если же написать как ты нарисовал
const std::string& s2 = function("Happy New Year");
то уходим на const std::string& function(const std::string& str).
Честно говоря размышлять про то кто прав VC++ или GCС здесь даже и не хочется. Не для production сей кунштюк.
Здравствуйте, c-smile, Вы писали:
CS>То же самое но в VC++ 2010 проделай.
CS>В ём родимом если написать так (явно)
CS>
CS>const std::string& s2 = function(std::string("Happy New Year"));
CS>
CS>то срабатывает функция std::string function(std::string&& str);
CS>Если же написать как ты нарисовал CS>
CS>const std::string& s2 = function("Happy New Year");
CS>
CS>то уходим на const std::string& function(const std::string& str).
К сожалению, десятки под рукой нет, попробовать не на чем, но охотно верю, что десятка ведет себя именно так.
CS>Честно говоря размышлять про то кто прав VC++ или GCС здесь даже и не хочется. Не для production сей кунштюк.
Размышлять тут особо не над чем: по-любому, тот же VC++ создал временный объект типа std::string (пусть даже неявно, что это меняет?), а потом для этого временного объекта неправильно выбрал кандидата на подстановку — очевидно, что неправ VC++.
CS>Не для production сей кунштюк.
Ну этот тезис неплохо бы хоть как-то аргументировать.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
CS>>Честно говоря размышлять про то кто прав VC++ или GCС здесь даже и не хочется. Не для production сей кунштюк.
R>Размышлять тут особо не над чем: по-любому, тот же VC++ создал временный объект типа std::string (пусть даже неявно, что это меняет?), а потом для этого временного объекта неправильно выбрал кандидата на подстановку — очевидно, что неправ VC++.
CS>>Не для production сей кунштюк.
R>Ну этот тезис неплохо бы хоть как-то аргументировать.
Когда в коде ты видишь это
function("Happy New Year");
то ты не можешь предсказать достоверно результат выражения.
Ты получаешь reference на временный объект которым неким магичесим образом будет иметь отметку "тянуть его до конца scope(?)". Причем в зависимости от фазы луны, используемого компайлера и его настроек. Шаманизм чистой воды — не для production.
Здравствуйте, c-smile, Вы писали:
CS>>>Не для production сей кунштюк.
R>>Ну этот тезис неплохо бы хоть как-то аргументировать.
CS>Когда в коде ты видишь это CS>
CS> function("Happy New Year");
CS>
CS>то ты не можешь предсказать достоверно результат выражения. CS>Ты получаешь reference на временный объект которым неким магичесим образом будет иметь отметку "тянуть его до конца scope(?)". Причем в зависимости от фазы луны, используемого компайлера и его настроек. Шаманизм чистой воды — не для production.
Соглашусь, что на сегодня, по текущей степени соответствия компиляторов стандарту, а также с учетом того, что новые фишки языка еще не получили достаточно широкого распространения, что по ним еще не наработано того, что называется "Best Practices", в продакшн такие вещи пока пускать не разумно. В особенности, если необходимо поддерживать переносимость кода. Но если на минуточку заглянуть в то счастливое будущее, когда компиляторы достаточно сносно будут выдерживать каноны, то, ИМХО, подобный код не должен вызывать каких-либо затруднений. Ведь достаточно взглянуть только на объявления этих перегрузок, что бы понять, что значения, возвращаемые этим семейством функций можно безопасно использовать для инициализации константных ссылок. И что при этом можно даже не задумываться о том, с каким объектом будет связана ссылка в том или ином случае — автоматическим, статическим или временным.
--
Справедливость выше закона. А человечность выше справедливости.
class X1
H>{
H>public:
H> Result const &f() const;
H> ....
H>};
H>class X2
H>{
H>public:
H> Result f() const;
H> ....
H>};
H>template < class X > void foo(X const &x)
H>{
H> Result const &result = x.f();
H> ....
H>}
H>В этом случае foo работает с одинаковой производительностью и с X1, и с X2. Если мы принимаем результат функции по значению, то в случае с X1 мы получаем лишнее копирование.
Это довольно специфический случай (причём сколь-нибудь заметное влияние такого лишнего копирования на производительность программы делает его ещё более специфическим). Мой поинт в том, что решение о выборе между Result const r = function(), Result const &r = function() и прочими вариантами должно приниматься в индивидуальном порядке, а те, кто используют Result const &r = function() на автопилоте, пускай пеняют на себя в случае чего.
c-smile:
CS>Здравствуйте, rg45, Вы писали:
CS>>>Возвращает 0. Или падает. Как карта ляжет.
R>>Падает, вероятно, от того, что у программы не нулевой код возврата, который, по видимому, расценивается как ошибка. Исправим это мелкое недоразумение и вот, уже ничего не падает: url=http://ideone.com/SvJEO
CS>То же самое но в VC++ 2010 проделай.
CS>В ём родимом если написать так (явно)
CS>
CS>const std::string& s2 = function(std::string("Happy New Year"));
CS>
CS>то срабатывает функция std::string function(std::string&& str);
CS>Если же написать как ты нарисовал CS>
CS>const std::string& s2 = function("Happy New Year");
CS>
CS>то уходим на const std::string& function(const std::string& str).
. Дело в том, что с момента выхода VC++ 10.0 до окончательного утверждения стандарта C++11 некоторые правила уже успели усовершенствовать. VC++ 10.0 — это компилятор с сырой и довольно скромной поддержкой неких устаревших draft-ов C++0x, оценивать по нему возможности C++11 некорректно.
Здравствуйте, Masterkent, Вы писали:
M>Это довольно специфический случай (причём сколь-нибудь заметное влияние такого лишнего копирования на производительность программы делает его ещё более специфическим).
Случай вполне обычный, когда X инкапсулирует тяжелый объект и предоставляет к нему константный доступ. При этом изначально этот объект мог быть легким и возвращаться при необходимости по значению.
M>Мой поинт в том, что решение о выборе между Result const r = function(), Result const &r = function() и прочими вариантами должно приниматься в индивидуальном порядке, а те, кто используют Result const &r = function() на автопилоте, пускай пеняют на себя в случае чего.
Мой пойнт был в выражении поддержки ononim. Для меня тоже Result const &r = function() будет кодом по умолчанию, а нарисованная выше функция function — специфичным случаем. Более того, грабли такой реализации функции довольно известны, и являются частным случаем "подумать, прежде чем возвращать значение из функции по ссылке".
. Дело в том, что с момента выхода VC++ 10.0 до окончательного утверждения стандарта C++11 некоторые правила уже успели усовершенствовать. VC++ 10.0 — это компилятор с сырой и довольно скромной поддержкой неких устаревших draft-ов C++0x, оценивать по нему возможности C++11 некорректно.
hmich:
M>>Это довольно специфический случай (причём сколь-нибудь заметное влияние такого лишнего копирования на производительность программы делает его ещё более специфическим).
H>Случай вполне обычный, когда X инкапсулирует тяжелый объект и предоставляет к нему константный доступ. При этом изначально этот объект мог быть легким и возвращаться при необходимости по значению.
Я уже указал на то, что такое изменение интерфейса является потенциальным breaking change, причём недиагностируемым на этапе трансляции (т.е. надо заново всё тщательно тестировать, а случае обнаруженного fail-а — ещё и тратить усилия на поиски новоиспечённого бага). Подобные изменения с целью какой-то мелкой оптимизации я бы у себя допускать не стал.
CS>> const std::string& s2 = std::string("Happy New Year");
CS>>
CS>>Вопрос: являются ли эти два выражения тождественными с точки зрения C++11?
A>В первом случае вызывается конструктор string из char const *, а за ним move-конструктор string.
Здравствуйте, alexeiz, Вы писали:
A>В первом случае вызывается конструктор string из char const *, а за ним move-конструктор string. Во втором просто конструктор string.
Я правильно понимаю идею что теперь (в C++11) эти двы выражения
const std::string s1("Happy New Year");
const std::string& s2 = std::string("Happy New Year");
c-smile:
CS>Я правильно понимаю идею что теперь (в C++11) эти двы выражения
CS>
CS>const std::string s1("Happy New Year");
CS>const std::string& s2 = std::string("Happy New Year");
CS>
CS>эквивалентны?
Это не выражения, а определения, и в целом они не эквивалентны, т.к. объявляемые сущности имеют разные имена и разные declared types (которые можно получить с помощью оператора decltype). К ссылке не может применяться NRVO. Если это member-ы некоего пространства имён, имеющего внешнее связывание, то у них будет разное связывание.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Сыроежка, Вы писали:
С>>Здравствуйте, rg45, Вы писали:
R>>>Здравствуйте, Сыроежка, Вы писали:
W>>>>>>>>Легален ли следующий код: O>>>>>>>легален, но будет летален в таком случае: O>>>>>>>
С>>>>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"? С>>>>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.
R>>>>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.
С>>>>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!
R>>>По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.
С>>Честно признаюсь, не понял, какое значение имеет раздельная компиляция? При вызове этой функции (не важно, где она определена) создается неименованный объъект, и создается ссылка на этот объект. Далее определение функции знает, что она получила ссылку и эту ссылку возвращает. То есть внутри функции никакие новые ссылки не создаются. Поэтому не вижу причем, почему раздельная компиляции как-то должна повлиять. Если бы это было так, то можно было бы сказать, что половина кода на С++ некоректные. Ведь как происходит удаление временных объектов? Компилятор смотрит, есть ли на него ссылки (не важно, сколько этих ссылок), и если нет, то удаляет объект. То же самое происходит и в этом конкретном случае. После вызова функции компилятор смотрит, есть ли ссылки на объект (а они есть, причем, как вы считаете, их может быть даже две, так как по вашему из-за раздельной компиляции компилятор не знает, что эти две ссылки одни и те же), и если есть, то объяект не удаляетася. И этот механизм не влияет на наличие раздельной компиляции.
R>Ну хорошо, давай рассмотрим пример: R>
R>Код вполне wel-formed и компилятор его успешно компилирует. Вопрос: по каким признакам компилятор должен понять, что временному объекту, созданному для передачи в функцию foo, нужно продлить время жизни?
Да, признаю, я глупость сморозил. Временный объект будет связан лишь с сылкой, объявленной в качестве параметра. А так как параметр функции имеет блочную область видимости, то при выходе из функции ссылка закончит свое существование, а потому и временный объект будет уничтожен.
Здравствуйте, Masterkent, Вы писали:
M>c-smile:
CS>>Я правильно понимаю идею что теперь (в C++11) эти двы выражения
CS>>
CS>>const std::string s1("Happy New Year");
CS>>const std::string& s2 = std::string("Happy New Year");
CS>>
CS>>эквивалентны?
M>Это не выражения, а определения, и в целом они не эквивалентны, т.к. объявляемые сущности имеют разные имена и разные declared types (которые можно получить с помощью оператора decltype). К ссылке не может применяться NRVO. Если это member-ы некоего пространства имён, имеющего внешнее связывание, то у них будет разное связывание.
Это всё понятно. Вопрос состоит в том когда будет вызван деструктор обоих строк.
В C++03 s2 есть ссылка на убитый объект — ctor и dtor в той же "строке".
В C++11 s2 есть ссылка на валидный объект — его dtor на выходе из scope.
Т.е. на самом деле ссылка может вызывать деструктор объекта на выходе из scope.
В месте объявления ссылки не всегда очевидно как эта ссылка получена.