tag:blogger.com,1999:blog-10303035.post5292359270003973675..comments2024-02-04T23:20:04.066+03:00Comments on Алёна C++: Возможно, самый важный constAlenahttp://www.blogger.com/profile/09389124127364799922noreply@blogger.comBlogger52125tag:blogger.com,1999:blog-10303035.post-84779243373556304292013-12-11T12:44:28.565+04:002013-12-11T12:44:28.565+04:00На StackOverflow уже ответили.
Expression k в конс...На StackOverflow уже ответили.<br />Expression k в конструкторе захватывает ссылку на временный объект, который разрушается сразу после завершения конструктора.<br />Дальнейшее - неопределённое поведение, которое в условиях оптимизации может выглядеть вообще как угодно.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-78492659224690480552013-12-10T09:25:16.562+04:002013-12-10T09:25:16.562+04:00Прокоментируйте этот код
http://stackoverflow.com/...Прокоментируйте этот код<br />http://stackoverflow.com/questions/20476669/g-segmentation-fault-when-enabling-optimization<br />Почему здесь ломается?Anonymoushttps://www.blogger.com/profile/06761857936274977661noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-53706158828522715822013-07-11T13:36:29.232+04:002013-07-11T13:36:29.232+04:00Исправить это элементарно.
first const& obj::g...Исправить это элементарно.<br />first const& obj::getM(void) <b>const</b><br /><br />что логично, поскольку getM ни меняет объект, ни отдаёт на сторону права на изменение.<br />Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-12246218339796143282013-07-08T21:31:12.214+04:002013-07-08T21:31:12.214+04:00Поясните пожалуйста как обходить следующий момет?
...Поясните пожалуйста как обходить следующий момет?<br /><br />class first<br />{<br />public:<br /> int i;<br />public:<br /> first &operator=(const first &in_This)<br /> {<br /> i = in_This.i;<br /> return(*this);<br /> }<br />};<br /><br />class obj<br />{<br />public:<br /> first mF;<br />public:<br /> obj()<br /> {<br /> }<br /> obj(obj &inThis)<br /> {<br /> mF = inThis.getM();<br /> }<br /> ~obj()<br /> {<br /> }<br /><br /> first &getM(first &out_m)<br /> {<br /> out_m = mF;<br /> return(out_m);<br /> }<br /> const first &getM(void)<br /> {<br /> return(mF);<br /> }<br /> obj &setM(const first &in_m)<br /> {<br /> mF = in_m;<br /> return(*this);<br /> }<br />};<br /><br />int _tmain(int argc, _TCHAR* argv[])<br />{<br /> setlocale( LC_ALL, ".1251" );<br /><br /> obj o;<br /> obj k;<br /> first f;<br /> k.setM(o.getM());<br /> k.setM(o.getM(f));<br /><br /> obj d(k);<br />}<br /><br />Все работает, но если что логично изменим функцию так:<br />obj(const obj &inThis)<br />{<br /> mF = inThis.getM();<br />}<br />Все ломается.<br /><br />Спасибо...Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10303035.post-48915033136430391412012-11-05T19:32:01.519+04:002012-11-05T19:32:01.519+04:00Так неважно же, где пользователь сохранит ссылку. ...Так неважно же, где пользователь сохранит ссылку. После выхода из функции ссылка на локальный объект инвалидируется. И в чём здесь хак? В том, чтобы получить ссылку на свежеосвобождённый участок стека?<br />Для стрельбы в ногу и низкоуровневой отладки, разве что.<br />Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-12586277602817652812012-11-02T23:58:40.193+04:002012-11-02T23:58:40.193+04:00al.zatv
А правильно ли делать вот так:
c...<b>al.zatv</b><br /><br /> <i> А правильно ли делать вот так:<br /><br /> const Obj &myFunc()<br /> {<br /> Obj x;<br /> return x;<br /> }<br /><br /> ? То есть, это функция, возвращающая константную ссылку на временный объект.<br /></i><br /><br />Зависит от того что понимать под "правильно". Синтаксис валидный. <br />Но нет гарантий, что пользователь будет создавать ссылку на стеке, компилятор на такой код выдаст предупреждение. Во всяких разных книгах по С++ не раз говорится "никогда не возвращайте ссылку на временный объект".<br /><br />Да и приведенный в статье путь трудно назвать "правильным". Это интересный с теоретической точки зрения хак, который я бы не стала использовать в промышленном коде.Alenahttps://www.blogger.com/profile/09389124127364799922noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-78869014644805337362012-10-31T11:47:18.908+04:002012-10-31T11:47:18.908+04:00А правильно ли делать вот так:
const Obj &myF...А правильно ли делать вот так:<br /><br />const Obj &myFunc()<br />{<br /> Obj x;<br /> return x;<br />}<br /><br />? То есть, это функция, возвращающая константную ссылку на временный объект.al.zatvhttps://www.blogger.com/profile/14913022741659864949noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-33497078448018270502010-03-17T14:09:53.997+03:002010-03-17T14:09:53.997+03:00Обидно, что при этом
const B& b = foo().b();
...Обидно, что при этом<br /><br />const B& b = foo().b();<br /><br />всё же не эквивалентно<br /><br />const A& a = foo(); <br />const B& a = a.b();Anonymoushttps://www.blogger.com/profile/02452782998088579717noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-28988182344299212292009-12-20T05:10:45.924+03:002009-12-20T05:10:45.924+03:00Во, кстати, на RSDN дискуссия трёхлетней давности ...Во, кстати, на RSDN дискуссия трёхлетней давности про оператор приведения к самому себе:<br />http://rsdn.ru/forum/cpp/1865794.aspx<br /><br />Прав комо, и причину он указывает в предупреждении:<br /><br /> "ComeauTest.c", line 4: warning: "self::operator self &()" will not be called for<br /> implicit or explicit conversions<br /> operator self & () { return (*this); }<br /><br />Причина:<br /><br />12.3.2/1<br />...<br />A conversion function is never used to convert a (possibly cv-qualified) <br />object to the (possibly cv-qualified) same object type (or a reference to it),<br />...Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-9320628199865307512009-12-20T03:26:40.770+03:002009-12-20T03:26:40.770+03:00Comeau, кстати, выдал варнинг о том, что тривиальн...Comeau, кстати, выдал варнинг о том, что тривиальный пользовательский оператор никогда не будет вызван.<br />Так что он здесь солидарен с VC.<br />Почему же gcc пошёл по другому пути - это загадка.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-4399080709796601052009-12-20T03:23:55.548+03:002009-12-20T03:23:55.548+03:002 elwood
Во-первых, здесь мы видим, что gcc не см...2 elwood<br /><br />Во-первых, здесь мы видим, что gcc не смог выполнить Return Value Optimization, а VC смог.<br /><br />Во-вторых, это действительно интересный вопрос: если в классе определён пользовательский оператор тривиального приведения типа - нужно ли пользоваться им (gcc), или забить (VC), или выдать ошибку?<br /><br />Нужно будет на RSDN спросить. И в стандарте порыться.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-77329645702043177442009-12-19T17:12:40.294+03:002009-12-19T17:12:40.294+03:00Недавно столкнулся с проблемой, которая может возн...Недавно столкнулся с проблемой, которая может возникнуть, если в класс, который передается в вызывающую функцию по ссылке, добавить оператор преобразования вида operator T& (). Пусть он ничего не делает и возвращает *this. Если класс Test содержит такой оператор, то GCC компилирует вызов функции <br /><br />Test someFunc()<br />{<br /> return Test();<br />}<br /><br />{<br /> printf("Begin\r\n");<br /> const Test& test = someFunc();<br /> printf("End\r\n");<br />}<br /><br />следующим образом (выводятся диагностические сообщения) :<br /><br />Begin<br />Default constructor<br />operator Test&<br />Copy constructor<br />Destructor<br />operator Test&<br />Destructor<br />End<br /><br />Visual C++ компилирует это иначе и программа выведет :<br /><br />Begin<br />Default constructor<br />End<br />Destructor<br /><br />Если отбросить лишние вызовы конструкторов копий / деструкторов (спишем это на отсутствие RVO в gcc), то остается главное отличие :<br />в Visual C++ переменная жива до выхода ссылки из области видимости, а GCC уничтожает её сразу.<br /><br />Пытался поискать описание такой ситуации в Стандарте 98, но, к сожалению, не нашел.<br /><br />Так какому же из компиляторов верить ?<br /><br />Лично мне кажется, что GCC себя ведет здесь неверно, поскольку в данном случае user-defined оператор T& ничем не отличается от генерируемого по умолчанию, но семантика вызова после добавления этого оператора преобразования коренным образом меняется.elwoodhttps://www.blogger.com/profile/17956281045134479078noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-74165339556828358272009-01-27T17:01:00.000+03:002009-01-27T17:01:00.000+03:002Анонимный:Кроме того, насколько я понял стандарт,...<B>2Анонимный:</B><BR/><BR/><I>Кроме того, насколько я понял стандарт, дело не в способе размещения(стек тут не причем), а в константности ссылки. </I><BR/><BR/>По-моему, стек там упоминается по отношению к объекту, жизнь которого продлевается, а не по отношению к ссылке.Alenahttps://www.blogger.com/profile/09389124127364799922noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-13361458250165855632009-01-16T21:50:00.000+03:002009-01-16T21:50:00.000+03:00Алён, а вот интересно, ты сама как думаешь, что та...Алён, а вот интересно, ты сама как думаешь, что такое ссылка в стеке, если ссылка вообще не объект по стандарту? ;) <BR/>Кроме того, насколько я понял стандарт, дело не в способе размещения(стек тут не причем), а в константности ссылки. Вот из стандарта(2003) пример(12.5/5):<BR/>[Example:<BR/>class C {<BR/>// ...<BR/>public:<BR/>C();<BR/>C(int);<BR/>friend C operator+(const C&, const C&);<BR/>˜C();<BR/>};<BR/>C obj1;<BR/>const C& cr = C(16)+C(23);<BR/>C obj2;<BR/><BR/>the expression C(16)+C(23) creates three temporaries. A first temporary T1 to hold the result of the<BR/>expression C(16), a second temporary T2 to hold the result of the expression C(23), and a third tempo-<BR/>rary T3 to hold the result of the addition of these two expressions. The temporary T3 is then bound to the<BR/>reference cr. It is unspecified whether T1 or T2 is created first. On an implementation where T1 is cre-<BR/>ated before T2, it is guaranteed that T2 is destroyed before T1. The temporaries T1 and T2 are bound to<BR/>the reference parameters of operator+; these temporaries are destroyed at the end of the full expression<BR/>containing the call to operator+. The temporary T3 bound to the reference cr is destroyed at the end of<BR/>cr’s lifetime, that is, at the end of the program. In addition, the order in which T3 is destroyed takes into<BR/>account the destruction order of other objects with static storage duration. That is, because obj1 is con-<BR/>structed before T3, and T3 is constructed before obj2, it is guaranteed that obj2 is destroyed before T3,<BR/>and that T3 is destroyed before obj1. ]<BR/><BR/>В общем смысл статьи Саттера в том, что константная ссылка продливает жизнь временного объекта, а неконстантную ссылку на временный объект создавать нельзя(ибо он rvalue).<BR/>А на счет стековой ссылки это он погорячился...<BR/><BR/>Д.К.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10303035.post-41042706797538702852009-01-04T02:14:00.000+03:002009-01-04T02:14:00.000+03:002 zmeysa:а такой код валиден? int& f() { in...<B>2 zmeysa:</B><BR/><BR/><I>а такой код валиден?<BR/><BR/> int& f() { int a = 1; return a; }<BR/></I><BR/><BR/>Меня напрягает уже вот эта строка, поскольку мы здесь пытаемся вернуть ссылку на локальную переменную.<BR/><BR/><A HREF="http://www.comeaucomputing.com/tryitout/" REL="nofollow">Comeau</A> на это выдает вполне ожидаемый warning.<BR/><BR/>warning: returning reference to local variableAlenahttps://www.blogger.com/profile/09389124127364799922noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-78536374232301697142008-12-31T16:44:00.000+03:002008-12-31T16:44:00.000+03:00а такой код валиден?int& f() { int a = 1; retu...а такой код валиден?<BR/><BR/>int& f() { int a = 1; return a; }<BR/><BR/>void g() {<BR/> const int& b = f();<BR/> cout << b << endl; <BR/>}Anonymoushttps://www.blogger.com/profile/17778107056998652381noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-62968043543519561622008-11-27T19:07:00.000+03:002008-11-27T19:07:00.000+03:00Собственно, никаких :)Просто было бы невежливо с м...Собственно, никаких :)<BR/>Просто было бы невежливо с моей стороны сделать это в обход хозяина блога.<BR/>---<BR/>Приглашаю всех заинтересованных участников продолжить обсуждение на RSDN, с любезного согласия Алёны.<BR/>http://www.rsdn.ru/Forum/?mid=3191155Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-48006520368336691092008-11-27T18:31:00.000+03:002008-11-27T18:31:00.000+03:002Kodt:AlenaC++, может быть, перевести дискуссию из...<B>2Kodt:</B><BR/><BR/><I>AlenaC++, может быть, перевести дискуссию из гостевухи в форум? Уж больно неудобно обсуждать код в "комментариях", изначально неприспособленных для этого.<BR/><BR/> Предлагаю родную для меня площадку - RSDN. http://www.rsdn.ru, форум С++.</I><BR/><BR/>Эээ... Переносите :-)<BR/>А от меня какие действия требуются?Alenahttps://www.blogger.com/profile/09389124127364799922noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-16494258953675515792008-11-27T16:40:00.000+03:002008-11-27T16:40:00.000+03:00AlenaC++, может быть, перевести дискуссию из госте...AlenaC++, может быть, перевести дискуссию из гостевухи в форум? Уж больно неудобно обсуждать код в "комментариях", изначально неприспособленных для этого.<BR/><BR/>Предлагаю родную для меня площадку - RSDN. http://www.rsdn.ru, форум С++.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-38158244147675084432008-11-27T16:37:00.000+03:002008-11-27T16:37:00.000+03:00"Поскольку ссылка константная" не являет..."Поскольку ссылка константная" не является причиной для продлевания жизни. Ещё раз: "const&" не IDDQD.<BR/><BR/>Давайте посмотрим, что происходит в коде --MapInt.end()<BR/><BR/>MapInt.end() возвращает rvalue - итератор на конец.<BR/><BR/>С++ позволяет вызывать неконстантные методы у rvalue; вот если бы автодекремент был внешней функцией, то здесь мы получили бы ошибку.<BR/><BR/>Итак, вызывается<BR/>iterator& iterator::operator--()<BR/>{.....; return *this; }<BR/>который возвращает неконстантную ссылку на самого себя.<BR/><BR/>Но компилятору-то уже пофиг, что это был временный объект. Сказано вернуть ссылку, нате.<BR/><BR/>Таким образом,<BR/>iterator const& clt = --MapInt.end();<BR/>неконстантная ссылка превращается в константную.<BR/><BR/>Дальше мы выходим за пределы полного выражения, временный объект погибает, ссылка инвалидируется.<BR/><BR/><I>Отчасти</I> проблему могут решить ссылки-на-rvalue (из стандарта C++0x).<BR/>Для этого итератор должен иметь два оператора автодекремента<BR/>iterator& operator--(iterator&);<BR/>iterator&& operator--(iterator&&);<BR/>(Я ещё не вкурил в новый стандарт, как это добро сделать членами; а на внешних функциях - вот так).Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-91140259703065965392008-11-27T15:13:00.000+03:002008-11-27T15:13:00.000+03:00В следующем коде что не так?#include <iostream...В следующем коде что не так?<BR/><BR/>#include <iostream><BR/>#include <map><BR/><BR/>typedef std::map<int, int> mapIntT;<BR/>mapIntT MapInt;<BR/><BR/>int main()<BR/>{ <BR/> MapInt.insert(std::pair<int, int>(1, 2));<BR/> mapIntT::iterator const& cIt = --MapInt.end();<BR/> if (cIt->second == cIt->first)<BR/> std::cout << "equal\n";<BR/> return 0;<BR/>}<BR/><BR/>В данном случае итератор - это объект. Он должен сохраняться, поскольку ссылка создается константная, или я чего-то недопонимаю?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10303035.post-89770730744565834252008-11-25T16:39:00.000+03:002008-11-25T16:39:00.000+03:002АнонимВидимо работает только для объектов, т.к. т...2Аноним<BR/><I>Видимо работает только для объектов, т.к. такой вариант не работает:</I><BR/><BR/>Это какая-то вера в магические заклинания "iddqd" и "const&"?<BR/><BR/>Вариант работает. Но не так, как вам хочется.<BR/><BR/>Поскольку (s1+s2) - это временный объект, то .c_str() возвращает указатель на временные данные.<BR/>Дальше - <B>сам указатель остаётся жить</B>, а данные помирают.<BR/><BR/>С равным успехом можно было взять итератор - (s1+s2).begin() - очень даже объект какого-то там класса.<BR/>Но этот объект не озадачивается <B>глубоким копированием</B> данных, связанных с ним.<BR/>И указатель не озадачивается.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-57967884703362363962008-11-25T16:21:00.000+03:002008-11-25T16:21:00.000+03:00Видимо работает только для объектов, т.к. такой ва...Видимо работает только для объектов, т.к. такой вариант не работает:<BR/><BR/>int main()<BR/>{<BR/> std::string str1 = "AAA";<BR/> std::string str2 = "BBB";<BR/> char const* const & cstr = (str1 + str2).c_str();<BR/> printf("\n%s\n", cstr);<BR/> return 0;<BR/>}Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-10303035.post-40873152275294469082008-11-17T13:39:00.000+03:002008-11-17T13:39:00.000+03:00Отчего const не оставляет объект?А отчего бы ему о...Отчего const не оставляет объект?<BR/>А отчего бы ему оставлять.<BR/><BR/>oss.str() возвращает временный объект, время жизни которого - до точки с запятой.<BR/><BR/>Далее, берём оттуда указатель на внутренние данные этого объекта.<BR/><BR/>Сам объект никак не продлеваем. Вот и наступает "фиаско".<BR/><BR/>А вот если бы написать<BR/><BR/>string const& s = oss.str();<BR/>char const* tmp = s.c_str();<BR/><BR/>то здесь первым пунктом мы продлеваем время жизни временного объекта - и можем пользоваться значением tmp столько, сколько живы внутренние данные.Kodthttps://www.blogger.com/profile/12739971468788709431noreply@blogger.comtag:blogger.com,1999:blog-10303035.post-18920682426159170132008-11-17T11:13:00.000+03:002008-11-17T11:13:00.000+03:00От чего const не сохраняет объект в этом случае? ...От чего const не сохраняет объект в этом случае?<BR/><BR/> std::ostringstream oss;<BR/> oss << "AAA";<BR/> const char* const& tmp = oss.str().c_str();<BR/><BR/>//далее tmp содержит невалидное значениеAnonymousnoreply@blogger.com