Re: Возвращение константной ссылки
От: ononim  
Дата: 30.12.11 06:52
Оценка: 1 (1) +3
W>Легален ли следующий код:
легален, но будет летален в таком случае:
const std::string &s = function( "foo" )
printf("s=%s\n",s.c_str());//kaboom
Как много веселых ребят, и все делают велосипед...
Re[3]: Возвращение константной ссылки
От: Анатолий Широков СССР  
Дата: 30.12.11 21:45
Оценка: +2 -2
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, rg45, Вы писали:


CS>А можно узнать что именно OK в этом коде:


CS>
CS>const std::string& s2 = function("Happy New Year!"); //OK!
CS>


CS>?


CS>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.


А продления времени жизни временного объекта, являющегося результатов выполнения перегруженной функции принимающей rvalue, не видно?
Re[13]: Возвращение константной ссылки
От: Masterkent  
Дата: 04.01.12 23:47
Оценка: 23 (2)
c-smile:

CS>Это всё понятно. Вопрос состоит в том когда будет вызван деструктор обоих строк.


CS>В C++03 s2 есть ссылка на убитый объект — ctor и dtor в той же "строке".

CS>В C++11 s2 есть ссылка на валидный объект — его dtor на выходе из scope.

Нет, s2 в обоих случаях указывает на временный объект, чьё время жизни совпадает со временем жизни ссылки. Разница между C++03 и C++11 состоит в том, что в рамках C++03 ссылка могла связываться как непосредственно с исходным объектом, так и с созданной копией исходного объекта (причём конструктор, выполняющий копирование, должен быть доступен независимо от того, какой из этих двух способов избирает реализация), а в рамках C++11 создание копии в данном контексте не разрешается и требования наличия конструктора, выполняющего копирование или перемещение, нет.

CS>В месте объявления ссылки не всегда очевидно как эта ссылка получена.


CS>
CS>const std::string& s1 = foo(); // foo() -> std:string
CS>const std::string& s2 = bar(); // bar() -> const std:string& 
CS>


CS>s1 и s2 здесь явно демонстрируют разное поведение (в плане вызова деструкторов).


Так оно и задумано. Если я ничего не забыл, правила C++11 — 12.2/5 касаются только следующих случаев:

1) temporary object, с которым связывается ссылка, создаётся в контексте её инициализации (см. 8.5.3/5/2/2, 8.5.4/3/5);

2) ссылка связывается непосредственно с тем объектом, который обозначает инициализирующее её выражение, и это выражение является prvalue.

В стандарте это довольно невнятно описано. Есть соотвествующая core issue (Issue 1299. “Temporary objects” vs “temporary expressions” — увы, пока без публично доступного описания) с запросом на уточнение правил.

В примере выше foo() — это prvalue, а bar() — lvalue (glvalue). glvalue не считается за temporary, даже если в действительности оно ссылается на temporary object. Ну а prvalue классового типа считается за temporary (за исключением случаев, предусмотренных в 5.2.2/11).
Re[7]: Возвращение константной ссылки
От: night beast СССР  
Дата: 30.12.11 14:04
Оценка: +2
Здравствуйте, Сыроежка, Вы писали:

W>>>>>>>Легален ли следующий код:

O>>>>>>легален, но будет летален в таком случае:
O>>>>>>
O>>>>>>const std::string &s = function( "foo" )
O>>>>>>printf("s=%s\n",s.c_str());//kaboom
O>>>>>>


С>>>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>>>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


С>>>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!


R>>По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.


С>Честно признаюсь, не понял, какое значение имеет раздельная компиляция? При вызове этой функции (не важно, где она определена) создается неименованный объъект, и создается ссылка на этот объект. Далее определение функции знает, что она получила ссылку и эту ссылку возвращает. То есть внутри функции никакие новые ссылки не создаются. Поэтому не вижу причем, почему раздельная компиляции как-то должна повлиять. Если бы это было так, то можно было бы сказать, что половина кода на С++ некоректные. Ведь как происходит удаление временных объектов? Компилятор смотрит, есть ли на него ссылки (не важно, сколько этих ссылок), и если нет, то удаляет объект. То же самое происходит и в этом конкретном случае. После вызова функции компилятор смотрит, есть ли ссылки на объект (а они есть, причем, как вы считаете, их может быть даже две, так как по вашему из-за раздельной компиляции компилятор не знает, что эти две ссылки одни и те же), и если есть, то объяект не удаляетася. И этот механизм не влияет на наличие раздельной компиляции.


не знаю о каком С++ ты говоришь, но в том си, который я знаю, компилятор не считает никаких ссылок на временные объекты, а честно удаляет созданные объекты в конце выражения.

что нетрудно проверить:
struct test {
  test () { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  test ( test const & ) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  ~test () { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

test const & foo ( test const & x ) { return x; }

int main () {
  test const & ref = foo( test() );
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Re[7]: Возвращение константной ссылки
От: Masterkent  
Дата: 31.12.11 06:58
Оценка: 3 (1)
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).

Похожий пример я уже приводил тут
Автор: Masterkent
Дата: 30.09.11
. Дело в том, что с момента выхода VC++ 10.0 до окончательного утверждения стандарта C++11 некоторые правила уже успели усовершенствовать. VC++ 10.0 — это компилятор с сырой и довольно скромной поддержкой неких устаревших draft-ов C++0x, оценивать по нему возможности C++11 некорректно.
Re[3]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 12:50
Оценка: +1
Здравствуйте, Сыроежка, Вы писали:

С>Здравствуйте, ononim, Вы писали:


W>>>Легален ли следующий код:

O>>легален, но будет летален в таком случае:
O>>
O>>const std::string &s = function( "foo" )
O>>printf("s=%s\n",s.c_str());//kaboom
O>>


С>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.
--
Справедливость выше закона. А человечность выше справедливости.
Re[7]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 14:09
Оценка: +1
Здравствуйте, Сыроежка, Вы писали:

С>Здравствуйте, rg45, Вы писали:


R>>Здравствуйте, Сыроежка, Вы писали:


W>>>>>>>Легален ли следующий код:

O>>>>>>легален, но будет летален в таком случае:
O>>>>>>
O>>>>>>const std::string &s = function( "foo" )
O>>>>>>printf("s=%s\n",s.c_str());//kaboom
O>>>>>>


С>>>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>>>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


С>>>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!


R>>По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.


С>Честно признаюсь, не понял, какое значение имеет раздельная компиляция? При вызове этой функции (не важно, где она определена) создается неименованный объъект, и создается ссылка на этот объект. Далее определение функции знает, что она получила ссылку и эту ссылку возвращает. То есть внутри функции никакие новые ссылки не создаются. Поэтому не вижу причем, почему раздельная компиляции как-то должна повлиять. Если бы это было так, то можно было бы сказать, что половина кода на С++ некоректные. Ведь как происходит удаление временных объектов? Компилятор смотрит, есть ли на него ссылки (не важно, сколько этих ссылок), и если нет, то удаляет объект. То же самое происходит и в этом конкретном случае. После вызова функции компилятор смотрит, есть ли ссылки на объект (а они есть, причем, как вы считаете, их может быть даже две, так как по вашему из-за раздельной компиляции компилятор не знает, что эти две ссылки одни и те же), и если есть, то объяект не удаляетася. И этот механизм не влияет на наличие раздельной компиляции.


Ну хорошо, давай рассмотрим пример:
#include <string>
#include <iostream>

const std::string& foo(const std::string&);

int main()
{
  const std::string& text = foo("bla-bla");
  std::cout << text << std::endl; 
}

Код вполне wel-formed и компилятор его успешно компилирует. Вопрос: по каким признакам компилятор должен понять, что временному объекту, созданному для передачи в функцию foo, нужно продлить время жизни?
--
Справедливость выше закона. А человечность выше справедливости.
Возвращение константной ссылки
От: wayfaring  
Дата: 30.12.11 05:55
Оценка:
Добрый день.

Легален ли следующий код:

const std::string & function( const std::string & str )
{
    return str;
}
Re: Возвращение константной ссылки
От: night beast СССР  
Дата: 30.12.11 05:57
Оценка:
Здравствуйте, wayfaring, Вы писали:

W>Добрый день.


W>Легален ли следующий код:


W>const std::string & function( const std::string & str )
W>{
W>    return str;
W>}


да
Re: Возвращение константной ссылки
От: SullenMan  
Дата: 30.12.11 06:07
Оценка:
Здравствуйте, wayfaring, Вы писали:

W>Добрый день.


W>Легален ли следующий код:


W>
W>const std::string & function( const std::string & str )
W>{
W>    return str;
W>}
W>


да, только зачем такое?
Re: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 08:04
Оценка:
Здравствуйте, wayfaring, Вы писали:

W>Легален ли следующий код:

W>...

Вот о чем подумалось. С появлением rvalue references появился способ обрабатывать временные объекты отдельно от остальных. И теперь можно защищать подобные функции от опасного использования, например так:

const std::string& function( const std::string& str)
{
    return str;
}
std::string function(std::string&& str) 
{
    return str;
}

Перегрузка, принимающая аргумент как rvalue reference, возвращает результат по значению. Благодаря этому использование function становится безопасным в любых вариантах:

std::string text = "Hello, World!";

const std::string& s1 = function(text);
const std::string& s2 = function("Happy New Year!"); //OK!

Хотя в некоторых случаях такой прием будет приводить к нежелательному копированию, например:

std::cout << function("bla-bla=bla") << std::endl;
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Возвращение константной ссылки
От: Masterkent  
Дата: 30.12.11 08:08
Оценка:
ononim:

W>>Легален ли следующий код:

O>легален, но будет летален в таком случае:
O>
O>const std::string &s = function( "foo" )
O>printf("s=%s\n",s.c_str());//kaboom
O>

Это проблемы вызывающего кода. Так же, как и в случае с

std::string s = function(0);

или

// если из function вернуть строку по значению, будет то же самое
char const *s = function("foo").c_str();
std::cout << s;
Re[3]: Возвращение константной ссылки
От: ononim  
Дата: 30.12.11 08:12
Оценка:
я же написал — что это легально, но к примеру у меня в привычках есть принимать возвращаемое значение-объект в конст-ссылку, и подозреваю не у меня одного, так что вышеописанный код — западло, но в определенных случаях (жесткая оптимизация) может быть оправдано
Как много веселых ребят, и все делают велосипед...
Re[4]: Возвращение константной ссылки
От: Кодт Россия  
Дата: 30.12.11 09:18
Оценка:
Здравствуйте, ononim, Вы писали:

O>я же написал — что это легально, но к примеру у меня в привычках есть принимать возвращаемое значение-объект в конст-ссылку, и подозреваю не у меня одного, так что вышеописанный код — западло, но в определенных случаях (жесткая оптимизация) может быть оправдано


Странная привычка. Экономия на cctor? Так ведь компилятор умеет экономить сам, выполняя RVO.

Код с протягиванием ссылки от параметра до возвращаемого значения может встречаться в разных expression template.
И задача его — не жёсткая оптимизация, а преобразование типов, либо просто терпимость к типам, которые noncopyable формально или по смыслу (тяжеловесные данные).
В отношении std::string это, конечно, выглядит пижонством и преждевременной оптимизацией.
Перекуём баги на фичи!
Re[4]: Возвращение константной ссылки
От: Masterkent  
Дата: 30.12.11 09:51
Оценка:
ononim:

O>я же написал — что это легально, но к примеру у меня в привычках есть принимать возвращаемое значение-объект в конст-ссылку, и подозреваю не у меня одного


Зачем так делать? Чем

Result f();
Result const &result = f();

лучше по сравнению с

Result f();
Result const result = f();

?
Правилами C++03 разрешалось создание любого конечного количества копий в обоих случаях. Правила C++11 требуют, чтобы ссылка result связывалась с исходным временным объектом непосредственно (без создания дополнительных копий), но очевидно, что для этого требуется тот же механизм, который можно использовать для RVO. Проверка доступности copy/move конструктора выполняется в контексте return statement вызываемой функции (инициализация ссылки снаружи функции эту проверку не устраняет). Любой вменяемый компилятор в обоих случаях поступит одинаково.

O>так что вышеописанный код — западло


Я так не считаю. Можно и при использовании возврата по значению накосячить:

#include <iostream>
#include <string>

std::string const &f1(std::string const &s)
{
    return s;
}

std::string f2(std::string const &s)
{
    return s;
}

std::string const &g1(std::string const &s)
{
    std::string const &result = f1(s);
    return result; // OK
}

std::string const &g2(std::string const &s)
{
    std::string const &result = f2(s);
    return result; // Ой!
}

int main()
{
    std::cout << g1("text") << std::endl; // OK
    std::cout << g2("text") << std::endl; // Ой!
}
Re[2]: Возвращение константной ссылки
От: Сыроежка  
Дата: 30.12.11 12:24
Оценка:
Здравствуйте, ononim, Вы писали:

W>>Легален ли следующий код:

O>легален, но будет летален в таком случае:
O>
O>const std::string &s = function( "foo" )
O>printf("s=%s\n",s.c_str());//kaboom
O>


Не могли бы вы объяснить, чем приведенный вами код будет "летален"?
Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

И чем ваш код отличается, например, от следующего кода

const int &r = 10;
Меня можно встретить на www.cpp.forum24.ru
Re[4]: Возвращение константной ссылки
От: Сыроежка  
Дата: 30.12.11 13:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Сыроежка, Вы писали:


С>>Здравствуйте, ononim, Вы писали:


W>>>>Легален ли следующий код:

O>>>легален, но будет летален в таком случае:
O>>>
O>>>const std::string &s = function( "foo" )
O>>>printf("s=%s\n",s.c_str());//kaboom
O>>>


С>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!
Меня можно встретить на www.cpp.forum24.ru
Re[5]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 13:21
Оценка:
Здравствуйте, Сыроежка, Вы писали:

W>>>>>Легален ли следующий код:

O>>>>легален, но будет летален в таком случае:
O>>>>
O>>>>const std::string &s = function( "foo" )
O>>>>printf("s=%s\n",s.c_str());//kaboom
O>>>>


С>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


С>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!


По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Возвращение константной ссылки
От: Сыроежка  
Дата: 30.12.11 13:52
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Сыроежка, Вы писали:


W>>>>>>Легален ли следующий код:

O>>>>>легален, но будет летален в таком случае:
O>>>>>
O>>>>>const std::string &s = function( "foo" )
O>>>>>printf("s=%s\n",s.c_str());//kaboom
O>>>>>


С>>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


С>>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!


R>По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.


Честно признаюсь, не понял, какое значение имеет раздельная компиляция? При вызове этой функции (не важно, где она определена) создается неименованный объъект, и создается ссылка на этот объект. Далее определение функции знает, что она получила ссылку и эту ссылку возвращает. То есть внутри функции никакие новые ссылки не создаются. Поэтому не вижу причем, почему раздельная компиляции как-то должна повлиять. Если бы это было так, то можно было бы сказать, что половина кода на С++ некоректные. Ведь как происходит удаление временных объектов? Компилятор смотрит, есть ли на него ссылки (не важно, сколько этих ссылок), и если нет, то удаляет объект. То же самое происходит и в этом конкретном случае. После вызова функции компилятор смотрит, есть ли ссылки на объект (а они есть, причем, как вы считаете, их может быть даже две, так как по вашему из-за раздельной компиляции компилятор не знает, что эти две ссылки одни и те же), и если есть, то объяект не удаляетася. И этот механизм не влияет на наличие раздельной компиляции.
Меня можно встретить на www.cpp.forum24.ru
Re[5]: Возвращение константной ссылки
От: hmich  
Дата: 30.12.11 16:18
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Зачем так делать? Чем


M>
Result f();
M>Result const &result = f();

M>лучше по сравнению с

M>
Result f();
M>Result const result = f();

M>?

В случае если сигнатура f изменится на

Result const & f();


(что бывает, например, когда f() член класса и значение сохраняется для использования в других функциях), вызывающий код не придется модифицировать чтобы он принимал возвращаемое значение по ссылке а не по значению.
Re[6]: Возвращение константной ссылки
От: Masterkent  
Дата: 30.12.11 18:49
Оценка:
hmich:

M>>Зачем так делать? Чем


M>>
Result f();
M>>Result const &result = f();

M>>лучше по сравнению с

M>>
Result f();
M>>Result const result = f();

M>>?

H>В случае если сигнатура f изменится на


H>
Result const & f();


H>(что бывает, например, когда f() член класса и значение сохраняется для использования в других функциях), вызывающий код не придется модифицировать чтобы он принимал возвращаемое значение по ссылке а не по значению.


Сомнительный аргумент. Таким невинным с виду изменением интерфейса можно и чей-нибудь код сломать:

class X
{
public:
    Result f();
    ....
};

void foo(X &x)
{
    Result const &result = x.f();
    modify(x);   // после этой строчки x.f() вернуло бы другой результат
    use(result); // используем старое значение x.f()
}

class X
{
public:
    Result const &f();
    ....
};

void foo(X &x)
{
    Result const &result = x.f();
    modify(x);   // после этой строчки значение по ссылке result изменилось
    use(result); // хотели использовать старое значение x.f(), а получили использование модифицированного объекта
}
Re[2]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 30.12.11 20:17
Оценка:
Здравствуйте, rg45, Вы писали:

А можно узнать что именно OK в этом коде:

const std::string& s2 = function("Happy New Year!"); //OK!


?

Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.
Re[7]: Возвращение константной ссылки
От: hmich  
Дата: 30.12.11 20:21
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>hmich:


M>Сомнительный аргумент. Таким невинным с виду изменением интерфейса можно и чей-нибудь код сломать:


M>
class X
M>{
M>public:
M>    Result const &f();
M>    ....
M>};

M>void foo(X &x)
M>{
M>    Result const &result = x.f();
M>    modify(x);   // после этой строчки значение по ссылке result изменилось
M>    use(result); // хотели использовать старое значение x.f(), а получили использование модифицированного объекта
M>}


Не спорю, этот прием имеет смысл только при работе с константными объектами.

class X1
{
public:
    Result const &f() const;
    ....
};

class X2
{
public:
    Result f() const;
    ....
};

template < class X > void foo(X const &x)
{
    Result const &result = x.f();
    ....
}


В этом случае foo работает с одинаковой производительностью и с X1, и с X2. Если мы принимаем результат функции по значению, то в случае с X1 мы получаем лишнее копирование.
Re[3]: Возвращение константной ссылки
От: innochenti  
Дата: 30.12.11 21:11
Оценка:
Здравствуйте, 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!"));
поправьте если не прав
Re[3]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 21:27
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, rg45, Вы писали:


CS>А можно узнать что именно OK в этом коде:


CS>
CS>const std::string& s2 = function("Happy New Year!"); //OK!
CS>


CS>?


"OK" в этом коде то, что ссылка не перестает быть действительной, сразу же после инициализации, как это было бы, если бы существовал только первый вариант перегруженной функции.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 30.12.11 22:38
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

CS>>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.


АШ>А продления времени жизни временного объекта, являющегося результатов выполнения перегруженной функции принимающей rvalue, не видно?


Нет, не видно. Может щательнее надо куда-то смотреть?

Вот эта программуля

#include <string>
#include <iostream>

const std::string& function(const std::string& str) 
{
    return str;
}

std::string function(std::string&& str) 
{
    return str;
}

int main(int argc, char* argv[])
{
  const std::string& s2 = function("Happy New Year"); 
  std::cout << "<" << s2 << ">" << std::endl;
  return s2.length();
}


Возвращает 0. Или падает. Как карта ляжет.
Вот вопрос у меня и возник — что значит тот OK?
Re[5]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 22:46
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Анатолий Широков, Вы писали:


CS>>>Кроме как получение reference на временный объект ничего не вижу. В обоих случаях.


АШ>>А продления времени жизни временного объекта, являющегося результатов выполнения перегруженной функции принимающей rvalue, не видно?


CS>Нет, не видно. Может щательнее надо куда-то смотреть?


CS>Вот эта программуля


CS>
CS>#include <string>
CS>#include <iostream>

CS>const std::string& function(const std::string& str) 
CS>{
CS>    return str;
CS>}

CS>std::string function(std::string&& str) 
CS>{
CS>    return str;
CS>}

CS>int main(int argc, char* argv[])
CS>{
CS>  const std::string& s2 = function("Happy New Year"); 
CS>  std::cout << "<" << s2 << ">" << std::endl;
CS>  return s2.length();
CS>}
CS>


CS>Возвращает 0. Или падает. Как карта ляжет.


Падает, вероятно, от того, что у программы не нулевой код возврата, который, по видимому, расценивается как ошибка. Исправим это мелкое недоразумение и вот, уже ничего не падает: url=http://ideone.com/SvJEO
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 30.12.11 23:00
Оценка:
Здравствуйте, 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 сей кунштюк.
Re[7]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 30.12.11 23:16
Оценка:
Здравствуйте, 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 сей кунштюк.


Ну этот тезис неплохо бы хоть как-то аргументировать.
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 30.12.11 23:42
Оценка:
Здравствуйте, rg45, Вы писали:

CS>>Честно говоря размышлять про то кто прав VC++ или GCС здесь даже и не хочется. Не для production сей кунштюк.


R>Размышлять тут особо не над чем: по-любому, тот же VC++ создал временный объект типа std::string (пусть даже неявно, что это меняет?), а потом для этого временного объекта неправильно выбрал кандидата на подстановку — очевидно, что неправ VC++.


CS>>Не для production сей кунштюк.


R>Ну этот тезис неплохо бы хоть как-то аргументировать.


Когда в коде ты видишь это
 function("Happy New Year");

то ты не можешь предсказать достоверно результат выражения.
Ты получаешь reference на временный объект которым неким магичесим образом будет иметь отметку "тянуть его до конца scope(?)". Причем в зависимости от фазы луны, используемого компайлера и его настроек. Шаманизм чистой воды — не для production.
Re[9]: Возвращение константной ссылки
От: rg45 СССР  
Дата: 31.12.11 00:10
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>>>Не для production сей кунштюк.


R>>Ну этот тезис неплохо бы хоть как-то аргументировать.


CS>Когда в коде ты видишь это

CS>
CS> function("Happy New Year"); 
CS>

CS>то ты не можешь предсказать достоверно результат выражения.
CS>Ты получаешь reference на временный объект которым неким магичесим образом будет иметь отметку "тянуть его до конца scope(?)". Причем в зависимости от фазы луны, используемого компайлера и его настроек. Шаманизм чистой воды — не для production.

Соглашусь, что на сегодня, по текущей степени соответствия компиляторов стандарту, а также с учетом того, что новые фишки языка еще не получили достаточно широкого распространения, что по ним еще не наработано того, что называется "Best Practices", в продакшн такие вещи пока пускать не разумно. В особенности, если необходимо поддерживать переносимость кода. Но если на минуточку заглянуть в то счастливое будущее, когда компиляторы достаточно сносно будут выдерживать каноны, то, ИМХО, подобный код не должен вызывать каких-либо затруднений. Ведь достаточно взглянуть только на объявления этих перегрузок, что бы понять, что значения, возвращаемые этим семейством функций можно безопасно использовать для инициализации константных ссылок. И что при этом можно даже не задумываться о том, с каким объектом будет связана ссылка в том или ином случае — автоматическим, статическим или временным.
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: Возвращение константной ссылки
От: Masterkent  
Дата: 31.12.11 06:57
Оценка:
hmich:

H>
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() на автопилоте, пускай пеняют на себя в случае чего.
Re[9]: Возвращение константной ссылки
От: hmich  
Дата: 31.12.11 12:17
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Это довольно специфический случай (причём сколь-нибудь заметное влияние такого лишнего копирования на производительность программы делает его ещё более специфическим).


Случай вполне обычный, когда X инкапсулирует тяжелый объект и предоставляет к нему константный доступ. При этом изначально этот объект мог быть легким и возвращаться при необходимости по значению.

M>Мой поинт в том, что решение о выборе между Result const r = function(), Result const &r = function() и прочими вариантами должно приниматься в индивидуальном порядке, а те, кто используют Result const &r = function() на автопилоте, пускай пеняют на себя в случае чего.


Мой пойнт был в выражении поддержки ononim. Для меня тоже Result const &r = function() будет кодом по умолчанию, а нарисованная выше функция function — специфичным случаем. Более того, грабли такой реализации функции довольно известны, и являются частным случаем "подумать, прежде чем возвращать значение из функции по ссылке".
Re[8]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 31.12.11 17:36
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Похожий пример я уже приводил тут
Автор: Masterkent
Дата: 30.09.11
. Дело в том, что с момента выхода VC++ 10.0 до окончательного утверждения стандарта C++11 некоторые правила уже успели усовершенствовать. VC++ 10.0 — это компилятор с сырой и довольно скромной поддержкой неких устаревших draft-ов C++0x, оценивать по нему возможности C++11 некорректно.


Семантически это вот:
  std::string function(std::string&& str) { return str; }
  const std::string& s1 = function("Happy New Year");


эквивалентно этому:
  const std::string& s2 = std::string("Happy New Year");


Вопрос: являются ли эти два выражения тождественными с точки зрения C++11?
Re[9]: Возвращение константной ссылки
От: alexeiz  
Дата: 02.01.12 03:42
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Семантически это вот:

CS>
CS>  std::string function(std::string&& str) { return str; }
CS>  const std::string& s1 = function("Happy New Year"); 
CS>


CS>эквивалентно этому:

CS>
CS>  const std::string& s2 = std::string("Happy New Year"); 
CS>


CS>Вопрос: являются ли эти два выражения тождественными с точки зрения C++11?


В первом случае вызывается конструктор string из char const *, а за ним move-конструктор string. Во втором просто конструктор string.
Re[10]: Возвращение константной ссылки
От: Masterkent  
Дата: 03.01.12 19:50
Оценка:
hmich:

M>>Это довольно специфический случай (причём сколь-нибудь заметное влияние такого лишнего копирования на производительность программы делает его ещё более специфическим).


H>Случай вполне обычный, когда X инкапсулирует тяжелый объект и предоставляет к нему константный доступ. При этом изначально этот объект мог быть легким и возвращаться при необходимости по значению.


Я уже указал на то, что такое изменение интерфейса является потенциальным breaking change, причём недиагностируемым на этапе трансляции (т.е. надо заново всё тщательно тестировать, а случае обнаруженного fail-а — ещё и тратить усилия на поиски новоиспечённого бага). Подобные изменения с целью какой-то мелкой оптимизации я бы у себя допускать не стал.
Re[10]: Возвращение константной ссылки
От: Masterkent  
Дата: 03.01.12 19:52
Оценка:
alexeiz:

A>Здравствуйте, c-smile, Вы писали:


CS>>Семантически это вот:

CS>>
CS>>  std::string function(std::string&& str) { return str; }
CS>>  const std::string& s1 = function("Happy New Year"); 
CS>>


CS>>эквивалентно этому:

CS>>
CS>>  const std::string& s2 = std::string("Happy New Year"); 
CS>>


CS>>Вопрос: являются ли эти два выражения тождественными с точки зрения C++11?


A>В первом случае вызывается конструктор string из char const *, а за ним move-конструктор string.


Не move, а copy. Если function определить так

std::string function(std::string&& str) { return std::move(str); }

то тогда будет перемещение.
Re[10]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 03.01.12 22:08
Оценка:
Здравствуйте, 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");


эквивалентны?
Re[11]: Возвращение константной ссылки
От: Masterkent  
Дата: 04.01.12 09:00
Оценка:
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-ы некоего пространства имён, имеющего внешнее связывание, то у них будет разное связывание.
Re[8]: Возвращение константной ссылки
От: Сыроежка  
Дата: 04.01.12 19:55
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Сыроежка, Вы писали:


С>>Здравствуйте, rg45, Вы писали:


R>>>Здравствуйте, Сыроежка, Вы писали:


W>>>>>>>>Легален ли следующий код:

O>>>>>>>легален, но будет летален в таком случае:
O>>>>>>>
O>>>>>>>const std::string &s = function( "foo" )
O>>>>>>>printf("s=%s\n",s.c_str());//kaboom
O>>>>>>>


С>>>>>>Не могли бы вы объяснить, чем приведенный вами код будет "летален"?

С>>>>>>Вы создаете временный неименованный объект, на который указывает константная ссылка. И пока ссулка будет жива, временный объект, на который сцществует константная сслыка, также будет жить, пока ссылка не выйдет за пределы области своей видимости.

R>>>>>Тем, что, в общем случае, у компилятора нет информации о том, что функция возвращает ссылку именно на тот объект, который был передан функции в качестве аргумента. Следовательно, и оснований для продления времени жизни этого объекта у компилятора нет. Ну разжевывали же уже эту ситуацию, даже не один раз ЕМНИП.


С>>>>Любопытно, почему у компилятора нет такой информации?! А на какой тогда по вашему объект возвращается ссылка?!


R>>>По принципу раздельной компиляции — эта функция может быть определена в другой единице трансляции. И внутреннее представление ссылок сравнить компилятор не может, потому, что во время компиляции их просто нет.


С>>Честно признаюсь, не понял, какое значение имеет раздельная компиляция? При вызове этой функции (не важно, где она определена) создается неименованный объъект, и создается ссылка на этот объект. Далее определение функции знает, что она получила ссылку и эту ссылку возвращает. То есть внутри функции никакие новые ссылки не создаются. Поэтому не вижу причем, почему раздельная компиляции как-то должна повлиять. Если бы это было так, то можно было бы сказать, что половина кода на С++ некоректные. Ведь как происходит удаление временных объектов? Компилятор смотрит, есть ли на него ссылки (не важно, сколько этих ссылок), и если нет, то удаляет объект. То же самое происходит и в этом конкретном случае. После вызова функции компилятор смотрит, есть ли ссылки на объект (а они есть, причем, как вы считаете, их может быть даже две, так как по вашему из-за раздельной компиляции компилятор не знает, что эти две ссылки одни и те же), и если есть, то объяект не удаляетася. И этот механизм не влияет на наличие раздельной компиляции.


R>Ну хорошо, давай рассмотрим пример:

R>
R>#include <string>
R>#include <iostream>

R>const std::string& foo(const std::string&);

R>int main()
R>{
R>  const std::string& text = foo("bla-bla");
R>  std::cout << text << std::endl; 
R>}
R>

R>Код вполне wel-formed и компилятор его успешно компилирует. Вопрос: по каким признакам компилятор должен понять, что временному объекту, созданному для передачи в функцию foo, нужно продлить время жизни?


Да, признаю, я глупость сморозил. Временный объект будет связан лишь с сылкой, объявленной в качестве параметра. А так как параметр функции имеет блочную область видимости, то при выходе из функции ссылка закончит свое существование, а потому и временный объект будет уничтожен.
Меня можно встретить на www.cpp.forum24.ru
Re[12]: Возвращение константной ссылки
От: c-smile Канада http://terrainformatica.com
Дата: 04.01.12 21:59
Оценка:
Здравствуйте, 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.
В месте объявления ссылки не всегда очевидно как эта ссылка получена.

const std::string& s1 = foo(); // foo() -> std:string
const std::string& s2 = bar(); // bar() -> const std:string&


s1 и s2 здесь явно демонстрируют разное поведение (в плане вызова деструкторов).

Несколько неожиданный side-effect на самом деле. Надо его думать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.